1

私はbashプログラミング(grep / uniq / sort / etc ...)を初めて使用し、指定された形式のファイルから重複を削除しようとして問題が発生します。

--
name: joe
tag: 123
--
name: mike
tag: 000
--
name: dave
tag: 123
--
name: loopy
tag: 123
--

基本的に私が欲しいのは、次のように、同じタグ番号を持つファイル内の重複を削除することです。

--
name: joe
tag: 123
--
name: mike
tag: 000
--
4

3 に答える 3

5

このタスクは awk に非常に適しています。gawk または mawk が利用できる場合は、レコード区切り文字を適切に設定することで実現できます。

awk -v RS='--\n' -v ORS='--\n' '!h[$4]++' infile

出力:

--
name: joe
tag: 123
--
name: mike
tag: 000
--

これは、どのタグが表示されたか ( h[$4]++)、つまり各レコードの 4 番目の要素を記憶することによって機能します。インクリメントの前のバング ( !) は、 がゼロの場合にのみ条件が true であることを保証するh[$4]ため、デフォルト ルール ( { print $0 }) は最初にタグが表示されたときにのみ呼び出されます。

少し短いバージョン:

awk '!h[$4]++' RS='--\n' ORS='--\n' infile

編集 - 名前フィールドにスペースがあるレコードを処理する

名前フィールドにスペースが含まれている場合、フィールド数は異なります。これは、フィールド分割を少し異なる方法で処理することで処理できます。

awk '!h[$4]++' RS='--\n' ORS='--\n' FS='\n| *: *' infile
于 2013-01-22T08:42:53.437 に答える
1
awk '/name/{x=$0}/tag/{a[$0]++;if(a[$0]<2){print "--\n"x,"\n",$0"\n--"}}' your_file

以下でテスト:

> cat temp
--
name: joe
tag: 123
--
name: mike
tag: 000
--
name: dave
tag: 123
--
name: loopy
tag: 123
--
> awk '/name/{x=$0}/tag/{a[$0]++;if(a[$0]<2){print "--\n"x,"\n",$0"\n--"}}' temp
--
name: joe 
 tag: 123
--
--
name: mike 
 tag: 000
--

/name/{次のタグが重複していない場合にこの一時変数を使用できるように、ここに行を変数に格納します。}

/tag/{行の数で連想配列を作成します。複数あると重複します。したがって、数が 1 の場合のみ出力します}

于 2013-01-22T06:58:52.057 に答える
-2

foob​​arが重複を削除する行を含むファイルである場合:

awk '{ if (arry[$3]++ == 0) print $0; }' foobar

配列の$3は、3番目の列の値のみに基づいて重複を削除することを示しています。重複した行全体を削除する場合は、代わりに$0を使用してください。

このようにawkを使用すると、入力行の順序を変更しないという追加の利点があります(sort / uniqは変更します)。

于 2013-01-22T08:21:06.573 に答える