如何从一行中提取一个/两个/三个相邻的单词?

时间:2014-12-02 07:45:14

标签: shell unix command-line awk

我想提取由空格分隔的相邻单词的所有可能组合 - 一个,两个,三个项目。也就是说,转换这一行:

a bc de fghi j

a
bc
de
fghi
j
a bc
bc de
de fghi
fghi j
a bc de
bc de fghi
de fghi j

如何尽快使用awk执行此操作?我绝对卡住了,不知道。我想过像match($0, /^([a-z]+)$|([^\s]+\s[^\s]+)|([^\s]+\s[^\s]+\s[^\s]+)/, arr)这样的东西,但它在这种情况下无效。

修改 关键问题是如何将其与使用split相结合。例如,

{split($0, arr, ",");
for (i = 1; i <= length(arr); i++) {
    print arr[i]
}
for (i = 1; i <= length(arr) - 1; i++) {
    print arr[i] " " arr(i+1)
}
for (i = 1; i <= length(arr) - 2; i++) {
    print arr[i] " " arr[i+1] " " arr[i+2]
}
}  

给出Call to undefined function

2 个答案:

答案 0 :(得分:1)

这是一个有点冗长的awk脚本,它将根据您提供的输入生成输出。

{
for (i = 1; i <= NF; i++) {
    print $i
}
for (i = 1; i <= NF - 1; i++) {
    print $i " " $(i+1)
}
for (i = 1; i <= NF - 2; i++) {
    print $i " " $(i+1) " " $(i+2)
}
}

像这样运行:

awk -f Extract.awk Input.txt

这是一个更适用于k > 3相邻单词的通用版本。

function join(array, start, end, sep, result, i)
{
    if (sep == "")
       sep = " "
    else if (sep == SUBSEP) # magic value
       sep = ""
    result = array[start]
    for (i = start + 1; i <= end; i++)
        result = result sep array[i]
    return result
}

{
for (i = 1; i <= NF; i++) {
    a[i] = $i    
}
for (k = 0; k < 3; k++) {
for (i = 1; i <= NF - k; i++) {
   result = join(a, i, i + k, " ") 
   print result
}
}
}

答案 1 :(得分:1)

您可以使用lookahead:

使用此perl命令
s='a bc de fghi j'
perl -ne 'print join "\n" =>$_ =~ /(?=\b(\w+)\b)/g; print "\n";
          print join "\n" =>$_ =~ /(?=\b(\w+\s+\w+)\b)/g; print "\n";
          print join "\n" =>$_ =~ /(?=\b(\w+\s+\w+\s+\w+)\b)/g; print "\n"' <<< "$s"
a
bc
de
fghi
j
a bc
bc de
de fghi
fghi j
a bc de
bc de fghi
de fghi j