4

この一見複雑なタスクに対する簡単な解決策があるかどうか、私は興味があります:

このファイルがあるとします:

lineone
linetwo
linethree
linefour

lineone
linetwo
linethree
linefour

lineone
lineone
lineone
linetwo
linethree
linefour

この結果を得るために考えられる簡単な方法はありますか:

lineone[1]
linetwo[1]
linethree[1]
linefour[1]

lineone[2]
linetwo[2]
linethree[2]
linefour[2]

lineone[3]
lineone[4]
lineone[5]
linetwo[3]
linethree[3]
linefour[3]

言葉で言えば、ファイル内での出現順に各行に番号を付けることができる単純な bash アルゴリズムはありますか? 追加のストレージを含む複雑なソリューションがなければ、これを行う方法を理解できません。また、回線の置換に使用する通常のコマンドは、ここでは役に立ちません。sed は、出現するすべての行を同じ値に置き換えるだけであり、文字列の置換 ( ${string/substring/replace} ) は行の順序を維持しないため、役に立ちません。

とても有難い。

4

3 に答える 3

3

次のawkコマンドは、行とその数の配列を保持することで機能します。

awk '{if($0~/./){a[$0]++;print $0"["a[$0]"]";} else print}' file

例:

$ cat file
lineone
linetwo
linethree
linefour

lineone
linetwo
linethree
linefour

lineone
linetwo
linethree
linefour

lineone
lineone
lineone
linetwo
linethree
linetwo

$ awk '{if($0~/./){a[$0]++;print $0"["a[$0]"]";} else print}' file
lineone[1]
linetwo[1]
linethree[1]
linefour[1]

lineone[2]
linetwo[2]
linethree[2]
linefour[2]

lineone[3]
linetwo[3]
linethree[3]
linefour[3]

lineone[4]
lineone[5]
lineone[6]
linetwo[4]
linethree[4]
linetwo[5]
于 2012-12-20T16:55:09.563 に答える
2

不可解な Perl ワンライナー:

perl -00 -lpe 's/$/"[". $. . "]"/gem'

あいまいな例に基づいて質問を誤解したようです。説明に従って行に番号を付けるための Perl スニペットを次に示します。

perl -lpe '/\S/ and $_ .= "[" . ++$n{$_} . "]"'
于 2012-12-20T21:17:34.650 に答える
2

100% 純粋な bash の簡単な回答:

#!/bin/bash

declare -A lines=()
while read -r l; do
    if [[ -n "$l" ]]; then
        echo "$l[$((++lines[$l]))]"
    else
        echo "$l"
    fi
done < file.txt

これは、必要に応じて、各 [空でない] 行にファイル内での出現順に番号を付けることができる単純な bash アルゴリズムです

これは最速の方法ではありません (awk答えはより高速で効率的ですが、awk答えはbash アルゴリズムではありません)。

秘訣はlines、キーがファイルの行である連想配列を使用し、空でない行が読み取られるたびに対応するキーの値をインクリメントすることです。

または、祖母に感銘を与えるためのワンライナー:

declare -A lines=(); while read -r l; do [[ -n "$l" ]] && echo "$l[$((++lines[$l]))]"; || echo "$l"; done < file.txt
于 2012-12-20T17:20:59.727 に答える