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

Shell 如何从一行中提取一个/两个/三个相邻单词?,shell,unix,command-line,awk,Shell,Unix,Command Line,Awk,我想提取由空格分隔的相邻单词的所有可能组合–一个、两个、三个项目。即,转换此行: a bc de fghi j 到 如何尽可能快地使用awk实现这一点?我完全被卡住了,不知道该怎么办。我考虑过类似于match($0,/^([a-z]+)$|([^\s]+\s[^\s]+)|([^\s]+\s[^\s]+\s[^\s]+)/,arr)但它在这种情况下无法工作 编辑 关键的问题是如何将此与使用拆分相结合。比如说, {split($0, arr, ","); for (i = 1; i <=

我想提取由空格分隔的相邻单词的所有可能组合–一个、两个、三个项目。即,转换此行:

a bc de fghi j

如何尽可能快地使用awk实现这一点?我完全被卡住了,不知道该怎么办。我考虑过类似于
match($0,/^([a-z]+)$|([^\s]+\s[^\s]+)|([^\s]+\s[^\s]+\s[^\s]+)/,arr)
但它在这种情况下无法工作

编辑 关键的问题是如何将此与使用
拆分
相结合。比如说,

{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]
}
}  
{split($0,arr,“,”);

对于(i=1;i这里有一个稍微冗长的
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)
}
}
下面是一个更通用的版本,适用于
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
}
}
}
函数联接(数组、开始、结束、sep、结果、i)
{
如果(sep==“”)
sep=“”
else如果(sep==subsp)#幻值
sep=“”
结果=数组[开始]

对于(i=start+1;i您可以使用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
s='a bc de fghi j'
perl-ne'print join“\n”=>$\u=~/(?=\ b(\w+)\b)/g;print“\n”;
打印联接“\n”=>$\u=~/(?=\ b(\w+\s+\w+\b)/g;打印“\n”;

print join“\n”=>$\u=~/(?=\ b(\w+\s+\w+\s+\w+\b)/g;print“\n”这是一个正确的脚本。有很多方法。这取决于你的逻辑。提示:使用数组你在第6行有一个输入错误。将
arr(i+1)
更改为
arr[i+1]
。哦,那太匆忙了!如果我要使用
split(str,arr,sep)谢谢你
,我能用
长度(arr)
arr[I]
替换
NF
$I
吗?@lyricallyevil我不明白为什么不能,但唯一真正知道的方法是尝试:)请检查更新。你能在假设
$0=split($0,arr,sep)的情况下编辑你的答案吗
?很好…在这种情况下,可以使用普通逗号代替
=>
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
}
}
}
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