$file
是一个csv(制表符分隔),有59列和64行。第1列始终是一个字符串,cols 2+总是一个整数(当值为NULL
时除外)。
cat ${file} | while read line
do awk -F'\t' '{ for (i=2; i<=NF; i++) print $1 "\t" $i "." }';
done;
输出:
Excellent .
Good .
…
然而将$i
切换为$2
仍有效:
Excellent 29.
Good 7.
…
为什么?
修改:
#lines 1 & 2 from data.csv (columns truncated for brevity):
Excellent 29 54 47 46 38 22 50
Good 7 14 27 24 26 36 20
#reform.sh
file=$1;
awk -F'\t' '{ for (i=2; i<=NF; i++) print $1 "\t" $i; }' ${file};
仍然像以前一样表现/返回。
解决:
批准的答案确实提供了AWK的正确输出。重新启动终端应用程序后,脚本按照描述执行。我无法确定终端应用程序问题的原因。
答案 0 :(得分:7)
我觉得你错了。你拥有的脚本没有输出任何智能的(a),因为当你试图将每一行读入$line
时,你实际上并没有将它们提供给{{ 1}}。
你可以用以下内容摆脱多余的(和不正确的)循环:
awk
如以下成绩单所示:
awk -F'\t' '{ for (i=2; i<=NF; i++) print $1 "\t" $i "." }' ${file}
正如您所看到的(虽然我使用的是空格而非标签),但这可以为您提供所需的输出。
为了回应你断言仍不能正常工作,我恐怕不得不乞求不同。以下脚本(带标签)显示它的效果与宣传的一样。
pax> echo 'A 1 2
...> B 3 4
...> C 5 6' >qq.in
pax> cat qq.in
A 1 2
B 3 4
C 5 6
pax> awk -F' ' '{ for (i=2; i<=NF; i++) print $1 " " $i "." }' qq.in
A 1.
A 2.
B 3.
B 4.
C 5.
C 6.
如果它实际上并不适用于您的环境,那就是另一个问题。您可能会遇到错误pax> cat qq.in
Excellent 29 54 47 46 38 22 50
Good 7 14 27 24 26 36 20
pax> awk -F'\t' '{ for (i=2; i<=NF; i++) print $1 "\t" $i; }' qq.in
Excellent 29
Excellent 54
Excellent 47
Excellent 46
Excellent 38
Excellent 22
Excellent 50
Good 7
Good 14
Good 27
Good 24
Good 26
Good 36
Good 20
或其他任何原因导致失败。
首先,找出您正在使用的awk
版本和操作系统,例如:
awk
(a):它确实会输出的东西,但几乎肯定不是你所期望的。让我们看看现实中发生的事情。请考虑以下与您的原文相似的成绩单:
awk --version
uname -a
现在看起来很奇怪,它似乎丢掉了第一行。
原因是pax> ( echo 1; echo 2; echo 3 ) | while read line ; do
...> awk '{print "[" $0 "]"}'
...> done
[2]
[3]
和while
之间的脱节。 awk
从标准输入读取第一行并将其分配给while
,然后执行$line
部分的正文。
该主体是do..done
,没有输入文件,因此从标准输入获取输入!
这意味着它将“吸收”其余的标准输入流并进行处理。
然后,它将返回awk
循环但是,如果标准输入没有更多数据,它将完成。它可能更好地说明:
while
如果您实际连接 pax> ( echo 1; echo 2; echo 3 ) | while read line ; do
...> echo "read: $line"
...> awk '{print "awk: " $0}'
...> done
read: 1
awk: 2
awk: 3
和while
以及awk
部分,您会看到它正常运行:
echo "$line" |
当然,在pax> ( echo 1; echo 2; echo 3 ) | while read line ; do
...> echo "$line" | awk '{print "[" $0 "]"}'
...> done
[1]
[2]
[3]
完全能够一次一个地处理多个行时,将输入分成行并将它们一次发送到awk
是没有意义的。自己的。
因此,在这个答案的第一个代码块中显示的单行awk
命令仍然是更好的方法。
答案 1 :(得分:2)
你可以做到
awk -F$'\t' '{ for (i=2; i<=NF; i++) print $1 "\t" $i "." }' FILE
而不是所有不需要的管道。