在 Linux 中选择正好有两列的行

在 Linux 中选择正好有两列的行

我有一个文件,它是文件名和相应转录本之间的映射。文件名和记录用制表符分隔。

文件的转录可能包含一个或多个由单个空格分隔的单词。以下是文件的布局,

[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

我还得到了那些只有一列的行,即“文件名”字段。

当我写入时NF<1没有输出(如预期)当我NF<2再次写入时没有输出(奇怪,它应该显示只有一列的行)当我写入时NF ==3我得到那些恰好有两列的行(再次令人困惑)

有什么问题吗?这真的很令人困惑。

现在我向您发送输入样本

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 的输出是那些完整的行(第一列和第二列都必须在那里)这是所需的输出

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>

我在文件 cll 上使用了以下命令(我的问题中的第一个示例)

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+,最后是第二列(最后一列)

  • ^表示行的开始并$表示行的结束


POSIX-ly:

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

答案2

其他答案,使用\s+过度匹配!\s也匹配数据中出现的空格。您正在寻找的是“Field_not_containing_TAB”,然后是“Tab”,然后是“Field_not_containing_TAB”。或者,用正则表达式来说,

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

Space注意:我的 rexexp 中的 ' 之间不应有任何字符egrep。由于我使用了kbd格式化标签,您可以在那里看到它们,我必须使用该标签才能使其Tab可见。

正则表达式匹配(或使用选项-v,egrep不匹配)提供的数据。

答案3

对你来说,两列是:something[TAB]something,something 中可以有一个空格。所以只需告诉 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]

变体:输出第二个单词非空的任何行:

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

相关内容