次のようなテキストがあるとしましょう。
file.txt 4 minutes 11 seconds 102 msec
file_1.txt 5 minutes 10 seconds 100 msec
file_3_2.txt 0 minutes 10 seconds 100 msec
を使用して数字とファイル名を維持しながらすべての単語を削除するにはsed
?
file.txt 4 11 102
file_1.txt 5 10 100
file_3_2.txt 0 10 100
答え1
必要なデータを抽出する方法はいくつかあります。
各行をスペースで区切られた複数のフィールドとして扱う場合、問題を解決するために使用できる最も基本的なツールは次のとおりですcut
。
$ cut -d ' ' -f 1,2,4,6 file
file.txt 4 11 102
file_1.txt 5 10 100
file_3_2.txt 0 10 100
これにより、ファイル内のスペースで区切られた最初、2番目、4番目、6番目のフィールドが抽出されます。
同様にawk
:
$ awk '{ print $1,$2,$4,$6 }' file
file.txt 4 11 102
file_1.txt 5 10 100
file_3_2.txt 0 10 100
これは同じことを行いますが、はるかに多くのコンテンツが含まれます。ツールawk
は入力をストリームとして扱います。記録で構成されるフィールド。デフォルトでは、レコードは1行にすぎず、フィールドは空白(スペースまたはタブ、複数可)で区切られたスペースではなくテキストです。フィールドをスペースで区切って、一度に1つのレコード(デフォルトでは一度に1行)の出力を生成します。
もう少し複雑な方法は、残りのデータから最初のフィールドを切り取り、残りのデータからすべての文字を削除してから、2つのフィールドを再貼り付けることです。
$ paste -d ' ' \
<( cut -d ' ' -f 1 file ) \
<( cut -d ' ' -f 2- file | tr -s '[:alpha:]' '[ *]' )
file.txt 4 11 102
file_1.txt 5 10 100
file_3_2.txt 0 10 100
しかし、これは入力を2回読み取るため、少しエレガントではありません。使用されるコマンドは、tr
すべてのアルファベット文字を空白に変更し、複数の連続した-s
空白のセットを単一の空白に「圧縮」(使用)します。
このpaste
コマンドは 2 つの入力ストリームを取得し、その間にスペース文字を入れて 1 行ずつ連結します。最初のストリームは、データから最初の列のみを抽出するコマンドを<( ... )
実行するcut
プロセス置換()によって提供されます。 2番目のストリームは、cut
列2のすべての列を抽出するために実行され、前述のようにtr
その列のアルファベット文字を空白に置き換える別のプロセス置換によって提供されます。
答え2
あなたの例があなたの問題にどれだけ具体的であるか明確ではありません。これが実際にあなたが要求するものであると仮定すると(これがクラスの練習になる可能性があることを心配します)、削除する3つの既知の文字列があり、最終的なシンボルを生成したいという事実を利用できます。それらの間には1つのスペースしかありません。非常に短いsedコマンドです。この例では、MacOSに付属のBSD sedを使用し、input.txtファイルの入力とstdoutの出力を使用します。
sed -E -e 's/ (minutes|seconds|msec)//g' < input.txt
これは、単一のスペースの後にターゲット文字列の1つが続くものと一致し、何もないものに置き換えます。最後の「g」は、同じ行に繰り返し適用されることを示します。
答え3
次のGNU sedコマンドを使用して問題を解決できます。
$ sed -Ee ' /(\s+\S+)\s+\S+/\1/g' file
我々は継続的に空白の単語を交互に使用し、次の空白の単語の組み合わせを拒否します。
答え4
1つの解決策は、「空白」と「数字以外の単語」の両方を削除することです。
$ sed -E 's/ \<[^0-9]*\>//g' file
file.txt 4 11 102
file_1.txt 5 10 100
file_3_2.txt 0 10 100