Bash 在awk中循环通过共享字段的行

Bash 在awk中循环通过共享字段的行,bash,loops,awk,Bash,Loops,Awk,我正在尝试编写一个awk脚本,它将所有共享一个公共字段(例如,第一个字段)的行循环两次,以实现它们之间所有可能的组合 最好用一个例子来解释——给出以下输入: cat input.txt A this A text B MORE B THINGS 我希望脚本构建所有可能的行组合,从“A”开始,然后是“B”。这就是输出: cat output.txt A this A this A text A this A this A text A text A text B MORE B MORE B

我正在尝试编写一个awk脚本,它将所有共享一个公共字段(例如,第一个字段)的行循环两次,以实现它们之间所有可能的组合

最好用一个例子来解释——给出以下输入:

cat input.txt

A this
A text
B MORE
B THINGS
我希望脚本构建所有可能的行组合,从“A”开始,然后是“B”。这就是输出:

cat output.txt

A this A this
A text A this
A this A text
A text A text
B MORE B MORE
B THINGS B MORE
B MORE B THINGS
B THINGS B THINGS
(所有可能的“本”和“文本”的组合+更多和“事物”的组合)

到目前为止,我得到了这个:

awk '{pair[++c] = $0 } END {
    for ( i = 1; i <= c; i++ ) {
        for ( j = 1; j <= c; j++ ){
            print pair[j], pair[i]
        }
    }
}' input.txt > output.txt
(它不考虑第一个字段是“A”还是“B”,只进行所有组合。)

有什么想法吗

我考虑过根据第一个字段分割输入文件,并对每个分割的文件进行双循环。但我需要一个解决方案,它也适用于第一个字段中有很多不同值的很长文件


谢谢

将GNU awk用于二维阵列:

$ cat tst.awk         
{ vals[$1][$0] }
END {
    for (key in vals) {
        for (val1 in vals[key]) {
            for (val2 in vals[key]) {
                print val1, val2
            }
        }
    }
}

$ gawk -f tst.awk file
A this A this
A this A text
A text A this
A text A text
B MORE B MORE
B MORE B THINGS
B THINGS B MORE
B THINGS B THINGS
或者,如果您的第一列始终按顺序排列,您可以使用任何awk执行此操作,它将使用更少的内存:

$ cat tst.awk
$1!=prev { shuffle() }
{ vals[$0]; prev=$1 }
END { shuffle() }

function shuffle(       val1, val2) {
    for (val1 in vals) {
        for (val2 in vals) {
            print val1, val2
        }
    }
    split("",vals)
}

$ awk -f tst.awk file
A this A this
A this A text
A text A this
A text A text
B MORE B MORE
B MORE B THINGS
B THINGS B MORE
B THINGS B THINGS
您可以避免使用数组:

cat input.txt| while read f1 fn; do
   awk '/^'$f1'/ {print "'$f1' '$fn' "$0 }' input.txt
done
编辑:将输入文件更改为input.txt,并添加了无awk解决方案:

对于每一行,awk都会启动,因此此解决方案可能会较慢(您可以进行测试)。 没有awk的解决方案将在每个循环中启动一个以上的程序:

cat input.txt| while read f1 fn; do
   grep "^$f1" input.txt | sed 's/^/'"${f1} ${fn}"'/'
done

第一个很有魅力,非常感谢!是的,我用的是gawk。第二种解决方案也可以,但我不会总是对文件进行排序+1我想我得到了你的答案,但我不确定每个文件(
输入
文件
)是什么。它们都是我指的同一个
input.txt
文件吗?@XGrau是的,你说得对。更改了它并添加了另一个解决方案。我想对于长文件来说速度会很慢,但不会耗尽内存。很好,两者都能很好地工作。的确,它们速度较慢,但对于小问题可能会起作用。我会投赞成票,但没有足够的代表性——无论如何,谢谢@沃尔特
cat input.txt| while read f1 fn; do
   grep "^$f1" input.txt | sed 's/^/'"${f1} ${fn}"'/'
done