行ごとに複数の列を持つ大容量ファイルがあります。cut -f -d
数字で特定の列を選択するのに慣れています。
マニュアルを確認しましたが、cut
正規表現一致列の方法がないようです。
私が具体的にしたいことは次のとおりです。
- 各行の2番目の列を選択
- 「hello」文字列を含むすべての列を選択します(何もない場合もあり、そうでない場合は任意の列になり、各行ごとに列が異なる場合があります)。
これを行う最も便利な端末ツールは何ですか?
編集する:
単純化された例
x ID23 a b c hello1
x ID47 hello2 a b c
x ID49 hello3 a b hello4
x ID53 a b c d
私が望む結果は次のとおりです。
ID23 hello1
ID47 hello2
ID49 hello3 hello4
または:
ID23 hello1
ID47 hello2
ID49 hello3 hello4
ID53
与えられた例の詳細な説明:
- 列は空白として定義されます。
- 「文字列が存在する場合にのみ印刷する」かどうかは重要ではありません。
grep
必要に応じて「hello」のみを印刷できます。 - 「hello」という文字列は、列1または2にはまったく現れないと仮定できます。
答え1
行末のスペースがあまり影響しない場合:
$ awk '{for(i=1;i<=NF;i++) if(i==2 || $i~"hello") printf $i" ";print ""}' file
ID23 hello1
ID47 hello2
ID49 hello3 hello4
ID53
これは、「hello」文字列の場所については何も仮定しません。
答え2
cut
または、少なくとも簡単ではないものを使用しているようです。 Perlソリューションは次のとおりです。
$ perl -lane '$k=join " ",grep{/hello/}@F; print "$F[1] $k" if $k' file
ID23 hello1
ID47 hello2
ID49 hello3 hello4
まず、次のように単純化できますgrep
。
$ grep hello file | perl -lane 'print "$F[1] ", join(" ", grep{/hello/}@F)'
ID23 hello1
ID47 hello2
ID49 hello3 hello4
説明する
この-n
オプションはperl
入力を1行ずつ読み込み、指定されたスクリプトを適用するように指示します-e
。このフラグは-l
各呼び出しに改行文字()を追加します。このオプションは、空白の入力行を配列に分割します。\n
print
-a
perl
@F
したがって、スクリプト自体は@F
一致するすべての要素(すべての列)を検索し、スペースで区切られたhello
文字列$k
($k=join " ",grep{/hello/}@F;
)として保存します。次に定義されていて1つ以上が見つかった場合は、2番目のフィールド($F[1]
)とを印刷します。$k
$k
hello
$k
2番目のバージョンは、少なくとも1つがhello
常に存在することを知っているため、直接印刷する必要がないことを除いて同じです。