sed
を使用する基本的な解決策は、comm
が接頭辞なしの最初のファイルにのみ行を出力するという事実に依存しています。 1つのタブで2番目のファイルにしかない行を出力します。 2つのタブで両方のファイルにある行を出力します。
また、ファイルに書き込むコマンドはsed
のw
コマンドに依存しています。
1.line-1
1.line-2
1.line-4
1.line-6
2.line-2
3.line-5
と含む2.sorted.txt
ファイル:
1.line-3
2.line-1
2.line-2
2.line-4
2.line-6
3.line-5
comm 1.sorted.txt 2.sorted.txt
からの基本的な出力は次のとおりです。
1.line-1
1.line-2
1.line-3
1.line-4
1.line-6
2.line-1
2.line-2
2.line-4
2.line-6
3.line-5
含むファイルscript.sed
考える:を含むファイル1.sorted.txt
を考えると
/^\t\t/ {
s///
w file.3
d
}
/^\t/ {
s///
w file.2
d
}
/^[^\t]/ {
w file.1
d
}
あなたは、以下のコマンドを実行して、このような所望の出力を得ることができます。
$ comm 1.sorted.txt 2.sorted.txt | sed -f script.sed
$ cat file.1
1.line-1
1.line-2
1.line-4
1.line-6
$ cat file.2
1.line-3
2.line-1
2.line-4
2.line-6
$ cat file.3
2.line-2
3.line-5
$
スクリプトがで動作します。削除、
2つのタブで始まる行に一致する
- タブを開き、
file.3
に行を書き込み、行を削除して(スクリプトの残りの部分は無視されます)、
- 行が1のタブで始まり、行を削除して(残りのスクリプトは無視されます)、
- と一致する行は、タブで始まらず、行を
file.1
に書き込み、その行を削除します。
ステップ3の一致および削除操作は、他のものよりも対称性があります。それらは省略することができ(ちょうどw file.1
を残す)、このスクリプトは同じように動作します。ただし、対称性を維持するためのさらなる正当性については、script3.sed
を参照してください。
GNU sed
が必要です。 BSD sed
は、\t
エスケープを認識しません。明らかに、ファイルは\t
表記の代わりに実際のタブで書かれていて、BSD sed
はスクリプトでOKです。
すべてをコマンドラインで動作させることは可能ですが、それは厄介なことです(それは丁寧です)。バッシュのANSI C Quotingを使用して、あなたが書くことができます別の-e
オプションでscript.sed
の3「段落」のそれぞれを書き込み
$ comm 1.sorted.txt 2.sorted.txt |
> sed -e $'/^\t\t/ { s///\n w file.3\n d\n }' \
> -e $'/^\t/ { s///\n w file.2\n d\n }' \
> -e $'/^[^\t]/ { w file.1\n d\n }'
$
を。 w
コマンドは難解です。ファイル名とファイル名だけがスクリプトの同じ行にあるので、スクリプト内のファイル名の後には\n
が使用されます。余りにも多くのスペースがありますが、レイアウトがわかるほど対称性が明確になります。 -f script.sed
ファイルを使用するほうが簡単でしょう。sed
スクリプトをシングルクォート、ダブルクォート、バッククォートで動作させる必要があるため、Bashのコマンドラインにスクリプトを書くのが難しいため、問題を避けることができます。
最後に、2つのファイルにタブで始まる行を含めることができれば、この手法はそれを機能させるにはもっと力強い力が必要です。 1つの変形ソリューションは、Bashのprocess substitutionを利用してファイル内の行の前にプレフィックスを追加し、出力ファイルに書き込む前に後処理sed
スクリプトで接頭辞を削除します。(最大8空白で置き換えタブ付き)
script3.sed
- (d
はまだ任意であるが、同様に含まれていてもよい)第三の段落に必要な代替s///
あり、このとき注意:
/^ X/ {
s///
w file.3
d
}
/^ X/ {
s///
w file.2
d
}
/^X/ {
s///
w file.1
d
}
とコマンドライン:同じ入力ファイルの場合
$ comm <(sed 's/^/X/' 1.sorted.txt) <(sed 's/^/X/' 2.sorted.txt) |
> sed -f script3.sed
$
、これは同じ出力を生成しますが、追加し、各行の先頭にX
を除去することで、コードは、cませんデータの並べ替え順序を変更し、先頭にタブがある場合は処理します。
また、PerlやAwkを使用するソリューションや、comm
を使用する必要がないソリューションも簡単に作成できます(ファイルがメモリに収まる場合は、未ソートファイルで作業することもできます)。
素晴らしい貢献。私たちはまだSOのドキュメントを持っていればよかったです。 BSD sedのユーザーに追加するべきことの1つ。もしあなたがFreeBSDにいるとしたら、あなたの '/ bin/sh'は* bashではないAlmquistシェルの間に、bashに似たCスタイルの引用を含みます。 – ghoti
@RomanPerekhrest:行頭に複数のタブ/スペースを先頭に(そして単語間に)追加すると動作しないようです。 – RomanPerekhrest
@RomanPerekhrest:あなたは、 'script3.sed'を使ったバリアントとプロセス置換がうまくいかないと言っていますか?データには先頭にタブがあるか、行内に複数の空白やタブがありますか?もしそうなら、私はサンプルデータを見たいと思います。あなたは電子メールで私にそれを送ってください - 私のプロフィールを見てください。考えられる1つの問題は、 'sort'と' comm'は、データがソートされた順序であることが何を意味するのかを目の当たりにしないということです。環境に 'LANG = C'を設定する必要があるかもしれません。 –