2

我的文本文件看起来像这样

foo.en 14 :: xyz 1;foo bar 2;foofoo 5;bar 9
bar.es 18 :: foo bar 4;kjp bar 2;bar 6;barbar 8

忽略::分隔符之前的文本,是否有一个衬里 unix 命令(允许许多管道)或一个衬里 perl 脚本来提取文本,从而产生由分隔的唯一单词的输出;

xyz
foo bar
foofoo
bar
kjp bar
barbar

我试过用 python 脚本循环遍历文本文件,但我正在寻找一个单行的任务。

ans = set()
for line in open(textfile):
  ans.add(line.partition(" :: ")[1].split(";").split(" ")[:-1])

for a in ans:
  print a
4

4 回答 4

3

使用 Perl:

perl -nle 's/.*?::\s*//;!$s{$_}++ and print for split /\s*\d+;?/' input

说明

s/.*?::\s*//;  # delete up to the first '::'

这部分:

!$s{$_}++ and print for split /\s*\d+;?/

可以这样重写:

foreach my $word (split /\s*\d+;?/) {   # for split /\s*\d+;?/
  if (not defined $seen{$word}}) {      # !$s{$_}
    print $word;                        # and print
  }
  $seen{$word}++;                       # $s{$_}++
}

由于 in 的增量!$s{$_}++是后增量,Perl 首先测试假条件,然后执行增量。未定义的哈希值具有值0。如果测试失败,即$s{$_}先前已递增,则and部分由于短路而被跳过。

于 2013-02-27T00:36:18.413 回答
2
cat textfile | sed 's/.*:://g' |  tr '[0-9]*;' '\n' | sort -u

解释:

sed 's/.*:://g'      Take everything up to and including `::` and replace it with nothing
tr '[0-9];' '\n'     Replace numbers and semicolon with newlines
sort -u              Sort, and return unique instances

我相信它确实会产生排序的输出......

于 2013-02-27T00:22:12.660 回答
1

你可以试试这个:

$ awk -F ' :: ' '{print $2}' input.txt | grep -oP '[^0-9;]+' | sort -u
bar 
barbar 
foo bar 
foofoo 
kjp bar 
xyz 

如果你的短语包含数字,试试这个正则表达式: '[^;]+?(?=\s+\d+(;|$))'

于 2013-02-27T00:24:41.253 回答
1

只有

$ awk -F' :: ' '{
    gsub(/[0-9]+/, "")
    split($2, arr, /;/ )
    for (a in arr) arr2[arr[a]]=""
}
END{
    for (i in arr2) print i
}' textfile.txt

还有一个单行版本:

 awk -F' :: ' '{gsub(/[0-9]+/, "");split($2, arr, /;/ );for (a in arr) arr2[arr[a]]="";}END{for (i in arr2) print i}' textfile.txt
于 2013-02-27T00:33:37.337 回答