Linuxで正確に2つの列を持つ行を選択する

Linuxで正確に2つの列を持つ行を選択する

ファイル名と対応する成績表の間のマップであるファイルがあります。ファイル名とレコードはタブで区切られます。

ファイル履歴には、単一のスペースで区切られた1つ以上の単語を含めることができます。以下はファイルのレイアウトです。

[filename] [tab space] [trancription]

一部の行では、転写列は空です。この行は次の形式です。

[filename]

つまり、このファイル名に使用できる履歴はありません。

今私の仕事は、ファイル名と転写(つまり、転写列が空でないファイル)を持つ行のみが選択されていることを確認することです。

私は次のコマンドを試しました

(1) awk 'NF>2' filename

(2) awk 'NF==2' filename

(3) awk 'NF>1' filename

しかし結果はありません。

また、コマンドを使用する場合

(4) awk ' NF==2 {print $0} '   myfile  > newfile

また、「ファイル名」フィールドという列が1つしかない行も取得します。

書き込み時にNF<1出力がありません(予想どおり)。NF<2書き換えると出力がありません(異常です。列が1つだけある行を表示する必要があります)。書くと、NF ==3正確に2つの列の行が表示されます(再び混乱しています)。

質問がありますか?本当に混乱しています。

これで入力サンプルをお送りします。

M07UP36A0821I40.wav 
M07UP36A0821I41.wav 
M07UP36A0821I410.wav    gaajara <bn>
M07UP36A0821I411.wav    tiina sau <pau> taintaaliisa
M07UP36A0821I412.wav    geehuun anya <bn>
M07UP36A0821I413.wav    geehuun daraa <babble>

ここでコマンドを使用します。

grep '^[^[:blank:]]\+[[:blank:]]\+[^[:blank:]]\+$' cll

コマンドは出力を提供しませんでした(ターミナルまたはリダイレクトされたファイルの両方で)。

今注目すべき興味深いことがあります。

入力ファイルに以下が含まれている場合

M07UP36A0822I413.wav    <bn> geehuun daraa <horn> <babble>
M07UP36A0822I414.wav    
M07UP36A0822I415.wav    gudxqa piilaa <horn> <babble>
M07UP36A0822I416.wav    <vn> gudxqa
M07UP36A0822I417.wav    gudxqa
M07UP36A0822I418.wav    gudxqa anya <babble>
M07UP36A0822I419.wav    harii matxara <bn> <babble>

また、同じコマンドを使用してください

grep '^[^[:blank:]]\+[[:blank:]]\+[^[:blank:]]\+$' foo

端末に出力が表示され始めました。ここで出力は次のようになります。

M07UP36A0822I417.wav    gudxqa

fooファイルに対して私が望む出力は完全な行です(最初の列と2番目の列の両方が必要です)。これが望ましい出力です。

M07UP36A0822I413.wav    <bn> geehuun daraa <horn> <babble>
M07UP36A0822I415.wav    gudxqa piilaa <horn> <babble>
M07UP36A0822I416.wav    <vn> gudxqa
M07UP36A0822I417.wav    gudxqa
M07UP36A0822I418.wav    gudxqa anya <babble>
M07UP36A0822I419.wav    harii matxara <bn> <babble>

私はclllファイルで次のコマンドを使用しました(私の質問の最初の例)

awk -F'\t' '(NF !=2) { print "line: " NR " does not have 2 columns: " $0 ;}' cll

結果が端末に表示されます。明らかにする

line: 1 does not have 2 columns: M07UP36A0821I40.wav 
line: 2 does not have 2 columns: M07UP36A0821I41.wav 
line: 3 does not have 2 columns: M07UP36A0821I410.wav    gaajara <bn>
line: 4 does not have 2 columns: M07UP36A0821I411.wav    tiina sau <pau> taintaaliisa
line: 5 does not have 2 columns: M07UP36A0821I412.wav    geehuun anya <bn>
line: 6 does not have 2 columns: M07UP36A0821I413.wav    geehuun daraa <babble>

答え1

使用grep:

grep -E '^[^\s]+\s+[^\s]+$' file.txt
  • [^\s]+最初の列、スペースの数\s+、最後に2番目の(最後の)列を含みます。

  • ^行の始まりを示し、$行の終わりを示します。


POSIX方式:

grep '^[^[:blank:]]\+[[:blank:]]\+[^[:blank:]]\+$' file.txt

答え2

他の答えは\s+オーバーマッチを使用してください!\sまた、データの空白の発生と一致します。あなたが探しているのは、「Field_not_含む_TAB」、「Tab」、「Field_not_を含む_TAB」の順です。または正規表現の用語で言うと

egrep '^[^Tab]+Tab[^Tab]+$' file.txt

Space注:私のrexexpの 'の間には文字を入れてはいけませんegrep。表示するために使用しなければならなかったフォーマットタグのため、そこから見ることkbdができます。Tab

正規表現は提供されたデータと一致します(またはoptionsを使用して一致しません)-vegrep

答え3

あなたに2つの列は何か[TAB]何かであり、何かに空白があるかもしれません。したがって、フィールド区切り文字がタブであることをawkに教えてください。

awk -F'\t' '(NF==2)'

また、誰かを調べてください。

awk -F'\t' '(NF !=2) { print "line: " NR " does not have 2 columns: " $0 ;}'

編集する:ファイル構造について「誤解を招く」ようです。ファイルには、1単語または1単語、タブ、および1つ以上の単語(スペースで区切られた)が含まれると言います。もしそうなら、上記のアプローチは効果的です。ただし、ファイルに対する上記のコマンドの結果を考慮すると、1つの単語、[スペースまたはタブ]、および単語[そして間にスペースまたはタブ]がある可能性があります。

したがって、解決策は次のとおりです。

awk -F'[\t ]+'  '(NF>=2)'    #words are separated by space&tabs, and we want at least 2 words [a filename, and its description]

バリアント:2番目の単語が空でない行を出力します。

awk -F'[\t ]+'  '(length($2)>0)'    #words are separated by space&tabs, and we want athe 2nd word to be non empty
#or, one that also verifies the 1st word is non empty:
awk -F'[\t ]+'  '(length($1)>0 && length($2)>0)'    #1st and 2nd words are non-empty

関連情報