如何在bash中一个接一个地打印列?
How to print columns one after the other in bash?
是否有更好的方法将两列或多列打印成一列,例如
input.file
AAA 111
BBB 222
CCC 333
输出:
AAA
BBB
CCC
111
222
333
我只能想到:
cut -f1 input.file >output.file;cut -f2 input.file >>output.file
但是如果有很多列,或者当我想将输出通过管道传输到其他命令(如 sort
.
时,那就不好了
还有其他建议吗?非常感谢!
和awk
awk '{if(maxc<NF)maxc=NF;
for(i=1;i<=NF;i++){(a[i]!=""?a[i]=a[i]RS$i:a[i]=$i)}
}
END{
for(i=1;i<=maxc;i++)print a[i]
}' input.file
丑陋,但它有效-
for i in {1..2} ; do awk -v p="$i" '{print $p}' input.file ; done
将 {1..2}
更改为 {1..n}
其中 'n'
是输入文件中的列数
说明-
我们正在定义一个变量 p,它本身就是变量 i。 i 从 1 到 n 变化,在每一步我们打印文件的第“i”列。
这将适用于 space 分隔列的任意数字
awk '{for (A=1;A<=NF;A++) printf("%s\n",$A);}' input.file | sort -u > output.file
Of space 不是分隔符...假设“:”是分隔符
awk -F: '{for (A=1;A<=NF;A++) printf("%s\n",$A);}' input.file | sort -u > output.file
awk '{print ;list[i++]=}END{for(j=0;j<i;j++){print list[j];}}' input.file
输出
AAA
BBB
CCC
111
222
333
更简单的解决方案是
awk -v RS="[[:blank:]\t\n]+" '1' input.file
您可以使用 GNU awk array of arrays 存储所有数据并稍后打印。
如果列数不变,这适用于任意数量的列:
gawk '{for (i=1; i<=NF; i++) # loop over columns
data[i][NR]=$i # store in data[column][line]
}
END {for (i=1;i<=NR;i++) # loop over lines
for (j=1;j<=NF;j++) # loop over columns
print data[i][j] # print the given field
}' file
注意NR
代表记录数(即这里的行数),NF
代表字段数(即给定行的字段数)。
如果列数随行数变化,那么我们应该使用另一个数组,在本例中用于存储每一行的列数。但是在问题中我没有看到对此的请求,所以我暂时离开它。
查看包含三列的示例:
$ cat a
AAA 111 123
BBB 222 234
CCC 333 345
$ gawk '{for (i=1; i<=NF; i++) data[i][NR]=$i} END {for (i=1;i<=NR;i++) for (j=1;j<=NF;j++) print data[i][j]}' a
AAA
BBB
CCC
111
222
333
123
234
345
如果列数不固定,使用数组存储每行的列数有助于跟踪它:
$ cat sc.wk
{for (i=1; i<=NF; i++)
data[i][NR]=$i
columns[NR]=NF
}
END {for (i=1;i<=NR;i++)
for (j=1;j<=NF;j++)
print (i<=columns[j] ? data[i][j] : "-")
}
$ cat a
AAA 111 123
BBB 222
CCC 333 345
$ awk -f sc.wk a
AAA
BBB
CCC
111
222
333
123
-
345
期望制表符作为分隔符:
$ cat <(cut -f 1 asd) <(cut -f 2 asd)
AAA
BBB
CCC
111
222
333
因为顺序不重要:
$ awk 'BEGIN {RS="[ \t\n]+"} 1' file
AAA
111
BBB
222
CCC
333
是否有更好的方法将两列或多列打印成一列,例如
input.file
AAA 111
BBB 222
CCC 333
输出:
AAA
BBB
CCC
111
222
333
我只能想到:
cut -f1 input.file >output.file;cut -f2 input.file >>output.file
但是如果有很多列,或者当我想将输出通过管道传输到其他命令(如 sort
.
还有其他建议吗?非常感谢!
和awk
awk '{if(maxc<NF)maxc=NF;
for(i=1;i<=NF;i++){(a[i]!=""?a[i]=a[i]RS$i:a[i]=$i)}
}
END{
for(i=1;i<=maxc;i++)print a[i]
}' input.file
丑陋,但它有效-
for i in {1..2} ; do awk -v p="$i" '{print $p}' input.file ; done
将 {1..2}
更改为 {1..n}
其中 'n'
是输入文件中的列数
说明-
我们正在定义一个变量 p,它本身就是变量 i。 i 从 1 到 n 变化,在每一步我们打印文件的第“i”列。
这将适用于 space 分隔列的任意数字
awk '{for (A=1;A<=NF;A++) printf("%s\n",$A);}' input.file | sort -u > output.file
Of space 不是分隔符...假设“:”是分隔符
awk -F: '{for (A=1;A<=NF;A++) printf("%s\n",$A);}' input.file | sort -u > output.file
awk '{print ;list[i++]=}END{for(j=0;j<i;j++){print list[j];}}' input.file
输出
AAA
BBB
CCC
111
222
333
更简单的解决方案是
awk -v RS="[[:blank:]\t\n]+" '1' input.file
您可以使用 GNU awk array of arrays 存储所有数据并稍后打印。
如果列数不变,这适用于任意数量的列:
gawk '{for (i=1; i<=NF; i++) # loop over columns
data[i][NR]=$i # store in data[column][line]
}
END {for (i=1;i<=NR;i++) # loop over lines
for (j=1;j<=NF;j++) # loop over columns
print data[i][j] # print the given field
}' file
注意NR
代表记录数(即这里的行数),NF
代表字段数(即给定行的字段数)。
如果列数随行数变化,那么我们应该使用另一个数组,在本例中用于存储每一行的列数。但是在问题中我没有看到对此的请求,所以我暂时离开它。
查看包含三列的示例:
$ cat a
AAA 111 123
BBB 222 234
CCC 333 345
$ gawk '{for (i=1; i<=NF; i++) data[i][NR]=$i} END {for (i=1;i<=NR;i++) for (j=1;j<=NF;j++) print data[i][j]}' a
AAA
BBB
CCC
111
222
333
123
234
345
如果列数不固定,使用数组存储每行的列数有助于跟踪它:
$ cat sc.wk
{for (i=1; i<=NF; i++)
data[i][NR]=$i
columns[NR]=NF
}
END {for (i=1;i<=NR;i++)
for (j=1;j<=NF;j++)
print (i<=columns[j] ? data[i][j] : "-")
}
$ cat a
AAA 111 123
BBB 222
CCC 333 345
$ awk -f sc.wk a
AAA
BBB
CCC
111
222
333
123
-
345
期望制表符作为分隔符:
$ cat <(cut -f 1 asd) <(cut -f 2 asd)
AAA
BBB
CCC
111
222
333
因为顺序不重要:
$ awk 'BEGIN {RS="[ \t\n]+"} 1' file
AAA
111
BBB
222
CCC
333