我有一个txt文件,共包含10177列,总共约450,000行。信息由选项卡分隔。我正在尝试使用awk修剪文件,以便它只在第五列之后打印1-3,5和每14列。
我的文件格式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ... 10177
A B C D E F G H I J K L M N O P Q R S T ...
X Y X Y X Y X Y X Y X Y X Y X Y X Y X Y ...
我希望生成一个输出txt文件(也用tab分隔),其中包含:
1 2 3 5 18 ...
A B C E R ...
X Y X X Y ...
我看起来的当前awk代码(我使用cygwin来使用代码):
$ awk -F"\t" '{OFS="\t"} { for(i=5;i<10177;i+=14) printf ($i) }' test2.txt > test3.txt
但我得到的结果显示如下:
123518...ABCER...XYXXY...
使用excel程序打开时,结果全部被分成1个单元格。
此外,当我尝试包含代码时
for (i=0;i<=3;i++) printf "%s ",$i
在awk中获取前3列,它只是打印出原始输入文档和mashed结果。我不熟悉awk,所以我不确定是什么导致了这个问题。
答案 0 :(得分:2)
Awk字段编号,字符串和数组索引都从1开始,而不是0,所以当你这样做时:
for (i=0;i<=3;i++) printf "%s ",$i
第一次迭代打印$0
,这是整个记录。
您通过以下方式走上正轨:
$ awk -F"\t" '{OFS="\t"} { for(i=5;i<10177;i+=14) printf ($i) }' test2.txt > test3.txt
但是从来没有使用输入数据作为printf的唯一参数printf,因为那时printf会把它当作没有数据的格式字符串(而不是你想要的那些是你的数据的普通字符串格式)然后这会以密码方式失败if /何时输入数据包含%s
或%d
等格式字符。因此,请始终使用printf "%s", $i
,而不是printf $i
。
我猜想,你在excel中遇到的问题是,你是否正试图双击该文件并希望excel知道如何处理它(它不会,不像是这是一个CSV)。您可以在打开标签分隔文件后将其导入excel - 谷歌即可。
你想要这样的东西:
awk '
BEGIN { FS=OFS="\t" }
{
for (i=1; i<=3; i++) {
printf "%s%s", (i>1?OFS:""), $i
}
for (i=5; i<=NF; i+=14) {
printf "%s%s", OFS, $i
}
print ""
}
' file
我强烈推荐Arnold Robbins撰写的Effective Awk Programming,第4版。
答案 1 :(得分:1)
在awk中使用for
中的条件运算符:
$ awk 'BEGIN { FS=OFS="\t" }
{
for(i=1; i<=NF; i+=( i<3 ? 1 : ( i==3 ? 2 : 14 )))
printf "%s%s", $i, ( (i+14)>NF ? ORS : OFS)
}' file
1 2 3 5 19
A B C E S
X Y X X X
在for
if i<3
增加1时,如果i==3
增加2,则增加到5,之后增加到14。
答案 2 :(得分:0)
我很想通过以下方式解决问题。我想你会发现你不用在awk中迭代来节省时间。
$ cols="$( { echo 1 2 3; seq 5 14 10177; } | sed 's/^/$/; 2,$ s/^/, /' )"
$ awk -F\\t "{print $cols}" test.txt