他のファイルのパターンと一致するすべての文字列を含むファイルを生成する方法

他のファイルのパターンと一致するすべての文字列を含むファイルを生成する方法

次のファイルがあります。

Dir1/File1.cpp Dir2/File2.cpp \
Dir3/File1.h Dir4/File2.cpp \
Dir2/File1.cpp \
Dir2/File1.h \

次のようなファイルを生成したいと思います。

Dir1/File1.cpp
Dir2/File2.cpp
Dir3/File1.h
Dir4/File2.cpp
Dir2/File1.cpp
Dir2/File1.h

Bash/Sed/Awk/Grep などを使用して、この操作をどのように実行できますか?

答え1

レコード区切り文字regexをサポートするAwkがある場合は、RS次のことができます。

awk 'BEGIN { RS = " +| *\\\\?\\n" } 1'

これの利点は、ファイル全体をメモリに入れず、いくつかの正規表現置換を行わずに入力長がギガバイトになることです。

デフォルトでは、ファイルを 2 つのレコード区切り文字として扱います。 1つ以上のスペースまたはゼロ個以上のスペースと改行文字の前にオプションのバックスラッシュを付けることができます。

このようにレコードを分離した場合、私たちがしなければならないことは、レコードを出力し、その後にデフォルトの出力レコード区切り文字(ORS)(もちろん改行文字)を付けることです。これは、以下で構成されるパターン作業規則によって達成されます1

sedあるいは、配管を使用し、trPOSIXに存在しないものを使用しないでください。

tr '\n' ' ' | sed -e 's/\\//g' -e 's/ \+/ /g' | tr ' ' '\n'

改行を空白に変更します。その後、バックスラッシュを削除しながら複数のスペースを1つに圧縮します。次に、スペースを改行文字にマップします。

答え2

GNUと共にgrep

$ cat file 
Dir1/File1.cpp Dir2/File2.cpp \
Dir3/File1.h Dir4/File2.cpp \
Dir2/File1.cpp \
Dir2/File1.h \

$ grep -o '[^\ ]*' file 
Dir1/File1.cpp
Dir2/File2.cpp
Dir3/File1.h
Dir4/File2.cpp
Dir2/File1.cpp
Dir2/File1.h
  • -o一致するパターンのみ抽出
  • [^\ ]*ゼロ個以上の非空白および非文字。貪欲な\ので、できるだけ多くの文字を一致させようとします。*

結果を別のファイルに保存するには、次のようにします。

$ grep -o '[^\ ]*' file > out_file


@Stéphane Chazelasが指摘したように、移植性のために以下を使用することをお勧めします。

grep -oE '[^\ ]+' file

-E拡張正規表現を呼び出し、スペースや文字で[^\ ]+はなく1つ以上と一致します。\


パフォーマンス分析:

$ perl -ne 'print "$_"x100000' file > file_big
$ shuf file_big -o file_big 

$ du -sh file_big 
9.0M    file_big

比較のためのコメントのすべての答えと提案:

$ time grep -o '[^\ ]*' file_big > o1

real    0m2.090s
user    0m2.076s
sys 0m0.016s

$ time grep -oE '[^\ ]+' file_big > o2

real    0m1.523s
user    0m1.504s
sys 0m0.012s

$ time awk 'BEGIN { RS = " +| *\\\\?\\n" } 1' file_big > o3

real    0m0.331s
user    0m0.320s
sys 0m0.008s

$ time tr -s '\\ ' '[\n*]' < file_big | grep . > o4

real    0m0.095s
user    0m0.124s
sys 0m0.008s

$ time tr '\\ ' '[\n*]' < file_big | grep . > o5

real    0m0.105s
user    0m0.104s
sys 0m0.016s

整合性チェック

$ diff -s o1 o2
Files o1 and o2 are identical
$ diff -s o1 o3
Files o1 and o3 are identical
$ diff -s o1 o4
Files o1 and o4 are identical
$ diff -s o1 o5
Files o1 and o5 are identical

関連情報