`cut`:文字列を含む列を選択する

`cut`:文字列を含む列を選択する

行ごとに複数の列を持つ大容量ファイルがあります。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各呼び出しに改行文字()を追加します。このオプションは、空白の入力行を配列に分割します。\nprint-aperl@F

したがって、スクリプト自体は@F一致するすべての要素(すべての列)を検索し、スペースで区切られたhello文字列$k$k=join " ",grep{/hello/}@F;)として保存します。次に定義されていて1つ以上が見つかった場合は、2番目のフィールド($F[1])とを印刷します。$k$khello

$k2番目のバージョンは、少なくとも1つがhello常に存在することを知っているため、直接印刷する必要がないことを除いて同じです。

関連情報