遍历在 awk 中共享一个字段的行
loop through lines sharing a field in 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 THINGS B MORE
B MORE B THINGS
B THINGS B THINGS
("this"和"text"的所有可能组合+"MORE"和"THINGS"的组合)
到目前为止,我得到了这个:
awk '{pair[++c] = [=12=] } END {
for ( i = 1; i <= c; i++ ) {
for ( j = 1; j <= c; j++ ){
print pair[j], pair[i]
}
}
}' input.txt > output.txt
但是输出是:
A this A this
A text A this
B MORE A this
B THINGS A this
A this A text
A text A text
B MORE A text
B THINGS A text
A this B MORE
A text B MORE
B MORE B MORE
B THINGS B MORE
A this B THINGS
A text B THINGS
B MORE B THINGS
B THINGS B THINGS
(不考虑第一个字段是"A"还是"B",只做所有的组合。)
有什么想法吗?
我考虑过根据第一个字段拆分输入文件并对每个拆分文件进行双循环。但我需要一个解决方案,该解决方案也适用于第一个字段中具有许多不同值的超长文件。
谢谢!
对二维数组使用 GNU awk:
$ cat tst.awk
{ vals[][[=10=]] }
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
!=prev { shuffle() }
{ vals[[=11=]]; prev= }
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' "[=10=] }' 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
我正在尝试编写一个 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
("this"和"text"的所有可能组合+"MORE"和"THINGS"的组合)
到目前为止,我得到了这个:
awk '{pair[++c] = [=12=] } END {
for ( i = 1; i <= c; i++ ) {
for ( j = 1; j <= c; j++ ){
print pair[j], pair[i]
}
}
}' input.txt > output.txt
但是输出是:
A this A this
A text A this
B MORE A this
B THINGS A this
A this A text
A text A text
B MORE A text
B THINGS A text
A this B MORE
A text B MORE
B MORE B MORE
B THINGS B MORE
A this B THINGS
A text B THINGS
B MORE B THINGS
B THINGS B THINGS
(不考虑第一个字段是"A"还是"B",只做所有的组合。)
有什么想法吗?
我考虑过根据第一个字段拆分输入文件并对每个拆分文件进行双循环。但我需要一个解决方案,该解决方案也适用于第一个字段中具有许多不同值的超长文件。
谢谢!
对二维数组使用 GNU awk:
$ cat tst.awk
{ vals[][[=10=]] }
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
!=prev { shuffle() }
{ vals[[=11=]]; prev= }
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' "[=10=] }' 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