リストをソートし、最初の列が一度だけ表示されるすべての行を印刷する方法を探しています。つまり、最初の列でのみ一致します。たとえば、最初の列がパスで、2番目の列に「type」を含むファイルがあります。
/path/foo/1 footsy
/path/foo/1 barsy
/path/foo/X barsy
/path/bar/2 footsy
/path/bar/2 barsy
/path/foo/Y footsy
(実際のファイルのソートは -k1,1 です)
それでは、次のような状況を抽出したいと思います。
/path/foo/X barsy
/path/foo/Y footsy
以前の行を保存し、前の行の最初のフィールドを現在の行の対応するフィールドと比較する必要があるawkを使用する方法を考えています。しかし、まだ何をすべきかわかりません。 :(他の質問で見つけた解決策を適用しようとしましたが、実際には望みどおりに機能しませんでした。
awk '{
prev=$0; path=$1; type=$2
getline
if ($1 != $path) {
print prev
}
}'
答え1
これらの回答には入力ソートは必要ありません。
数と最後の行を配列に保存します。大容量ファイルには多くのメモリが必要で、GNU awkが必要です。
gawk '
{count[$1]++; line[$1]=$0}
END {
PROCINFO["sorted_in"]="@val_str_asc"
for (key in line) if (count[key] == 1) print line[key]
}
' file
ファイルを2回スキャンし、最初に数を取得し、次に1に行を印刷します。
awk 'NR == FNR {count[$1]++; next} count[$1]==1' file file
ソートされた入力を活用するには、最速で最小限のメモリが必要です。
awk '
prev_key && prev_key != $1 {if (count==1) print prev_line; count=0}
{prev_key=$1; prev_line=$0; count++}
END {if (count==1) print prev_line}
' file
答え2
awk
通常、各入力行を読み取り、その行のスクリプトが呼び出されます。あなたがそれを使用する状況はgetline
ほとんどありません。以下は、6行の入力でスクリプトを実行したときに何が起こるのかについての概要です。最初の行を正常に読んでください
Call変数を設定しgetline
、2行を読み取り
、変数を比較します。3行目を正常に読んでください
Call変数を設定し、getline
行4を読み、
変数を比較します。5行目を正常に読んでください
Call変数を設定し、getline
行6を読み、
変数を比較します。明らかにこれはうまくいきません。
第二に、コードでよく見られる間違いを犯しています
awk
。のawk
入力のフィールドは次に参照され、変数は次に参照されます。$number
variable_name
。これは、コマンドラインパラメータがとして引用され、変数がとして引用されるシェルスクリプトとは異なります。あなたのテスト$number
$variable_name
if ($1 != $path)
しなければならない
if ($1 != path)
全体的なアプローチに欠陥があります。一度に2行を見ると、ファイルに一度だけ表示される文字列を識別できません。私は一度に3つの行を見ながらこれを行うことができると思います(例:二つ変数の最初の数行)しかし、それらは複雑で混乱しています。発生回数を計算する方が簡単な場合があります。これを行うには、スクリプトを最小限に変更する必要があります。
awk '{ if ($1 != path) { if (count == 1) { print prev } count=1 } else count++ prev=$0; path=$1 } END { if (count == 1) { print prev } }'
type
使用したことがないので削除しました。公開:これは本質的にGlennの答えの最後の部分と同じです。
答え3
シェルがサポートしている場合プロセスの交換、スペースやタブを含めないでくださいX
。Y
$ grep -Ff <(awk '{print $1" "}' <file | LC_ALL=C uniq -u) <file
/path/foo/X barsy
/path/foo/Y footsy
答え4
以下を試してみてください。
cat text.tx | sort | uniq -c -w11 | fgrep '1 /' | awk '{print $2" "$3}'
あなたのtext.txtは次のとおりです
]#cat text.txt
/path/foo/1 footsy
/path/foo/1 barsy
/path/foo/X barsy
/path/bar/2 footsy
/path/bar/2 barsy
/path/foo/Y footsy