これはフォローアップです。前の質問。フィールドの間隔が異なる場合でも、この構文を使用して重複行を削除します。
awk '{$1=$1};!NF||!seen[$0]++' /tmp/fstab
今から始まる行を除外したいと思います#
。だから私はこの構文を使います。
awk '/^#/ || "'!'"'{$1=$1};!NF||!seen[$0]++' /tmp/fstab
-bash: !: event not found
私の文法に何の問題がありますか?
答え1
どうですか?
awk '!NF||$1~/^#/ {print; next} {$1=$1} !seen[$0]++' /tmp/fstab
これにより、空白行または最初のフィールドが始まる行がすぐに印刷され、#
実行をスキップして追加のコードを無視します。他のすべての行は、まだ見つからない限り再構成され印刷されます。
$1~/^#/
行全体に一致を適用するのではなく(つまり、単に)ifをチェックする理由は、前にスペースがあるコメント行を/^#/
キャッチできるようにするためです。#
マンページではfstab
注釈を与える資格を得るために次の事項が必要ですが、最初文字はでなければならず、#
@StephenKittが指摘したように、Linux実装は先行スペースをスキップし、コメントを1行で許可しlibmount
ます。空でない最初キャラクターは#
。
答え2
bash
文句を言って(ないawk
)周りに一重引用符があるので、!
問題は明らかです。終了するコマンドブロックですawk
。
awk '{$1=$1} /^#/ || !seen[$0]++' file
つまり、まず作業を実行してから確認してください。欠点:コメントのスペースも削除/行ですが、そのような重複エントリは削除しません。まず、行をバッファリングしてこれを防ぎます。
awk '{a=$0 ; $1=$1} /^#/ || !seen[$0]++ {print a}' file
入力する:
#comment
duplicate line
#comment
duplicate line
not duplicate
not duplicate 2
duplicate line
#comment2
#comment2
#comment 3
#comment 3
出力(最初のコード)
#comment
duplicate line
#comment
not duplicate
not duplicate 2
#comment2
#comment2
#comment 3
#comment 3
出力(2番目のコード)
#comment
duplicate line
#comment
not duplicate
not duplicate 2
#comment2
#comment2
#comment 3
#comment 3
答え3
GNU sed
拡張正規表現モードオン-E
sed -Ee '
# print empty|blank|comment lines
/^\s*(#|$)/b
s/\s+/ /g;s/^ | $//g;G; # squeeze whitespace n append previous unique lines
/^([^\n]*)\n(.*\n)?\1(\n|$)/d; # delete if seen
P;h;d; # print seen first time then update seen list
' file