有没有更好的方法(例如AWK中的一个班轮)我可以在列表名称中使用标题获取列号?我希望能够独立于列号的实际处理列(例如,当添加另一列时,脚本不需要更改).
例如,给定"table.tsv"中的下表:
ID Value Target Not Used
1 5 9 11
2 4 8 12
3 6 7 10
Run Code Online (Sandbox Code Playgroud)
我可以使用以下方法对"目标"列进行排序:
#!/bin/bash
(IFS=$'\t'; read -r; printf "%s\n" "$REPLY"; i=0; for col in $REPLY; do
((++i))
[ "$col" == "Target" ] && break
done; sort -t$'\t' "-k$i,${i}n") < table.tsv
Run Code Online (Sandbox Code Playgroud)
有没有办法没有for循环(或至少清理一下)?
给定脚本的预期输出是:
ID Value Target Not Used
3 6 7 10
2 4 8 12
1 5 9 11
Run Code Online (Sandbox Code Playgroud)
但是,我试图给出一个我想要做的事情的例子.我想通过几个程序传递/过滤我的表,因此应保留标题和所有列:只需在每一步进行处理.在伪代码中,我想做的是:
print headings from stdin
i=$(magic to determine column position given "Target")
sort -t$'\t' "-k$i,${i}n" # or whatever processing is required on that column
Run Code Online (Sandbox Code Playgroud)
另一种有很多管道的替代品
$ head -1 table | tr -s ' ' '\n' | nl -nln | grep "Target" | cut -f1
Run Code Online (Sandbox Code Playgroud)
提取第一行,转置,数字行,查找列名,提取数字
或者,awk为了救援!
$ awk -v RS='\t' '/Target/{print NR; exit}' file.tsv
3
Run Code Online (Sandbox Code Playgroud)
这是一个 awk 替代方案:
awk -F '\t' -v col='Target' 'NR==1{for (i=1; i<=NF; i++) if ($i == col){c=i; break}}
{print $c}' file
Run Code Online (Sandbox Code Playgroud)
编辑:仅打印列号:
awk -F '\t' -v col='Target' 'NR==1{for (i=1; i<=NF; i++) if ($i==col) {print i;exit}}' file
3
Run Code Online (Sandbox Code Playgroud)