awk命令使用for循环打印多列
我有一个单独的文件,其中包含第一个和第二个列,其中包含项目代码和名称,然后是第三个列到第十二个列,其中包含连续10天的消耗数量。 现在我需要将它转换成10个不同的文件。在每个第一和第二栏应该是相同的项目代码和项目名称和第三列将包含在每一天的消费量..awk命令使用for循环打印多列
输入文件:
Code | Name | Day1 | Day2 | Day3 |...
10001 | abcd | 5 | 1 | 9 |...
10002 | degg | 3 | 9 | 6 |...
10003 | gxyz | 4 | 8 | 7 |...
我需要的输出在不同的文件作为
文件1:
Code | Name | Day1
10001 | abcd | 5
10002 | degg | 3
10003 | gxyz | 4
文件2:
Code | Name | Day2
10001 | abcd | 1
10002 | degg | 9
10003 | gxyz | 8
文件3:
Code | Name | Day3
10001 | abcd | 9
10002 | degg | 6
10003 | gxyz | 7
等等....
我写了这样的
awk 'BEGIN { FS = "\t" } ; {print $1,$2,$3}' FILE_NAME > file1;
awk 'BEGIN { FS = "\t" } ; {print $1,$2,$4}' FILE_NAME > file2;
awk 'BEGIN { FS = "\t" } ; {print $1,$2,$5}' FILE_NAME > file3;
等代码...
现在我需要写在'for'或'while'循环中,这会更快...
我不知道确切的代码,可能是这样的..
for ((i=3; i<=NF; i++)) ; do awk 'BEGIN { FS = "\t" } ; {print $1,$2,$i}' input.tsv > $i.tsv; done
好心帮我得到的输出作为我解释。
如果绝对需要猛砸来使用一个循环,那么你的循环可以固定这样的:
for ((i = 3; i <= 10; i++)); do awk -v field=$i 'BEGIN { FS = "\t" } { print $1, $2, $field }' input.tsv > file$i.tsv; done
但它会真的更好解决这个问题,使用纯awk,根本没有外壳:
awk -v FS='\t' '
NR == 1 {
for (i = 3; i < NF; i++) {
fn = "file" (i - 2) ".txt";
print $1, $2, $i > fn;
print "" >> fn;
}
}
NR > 2 {
for (i = 3; i < NF; i++) {
fn = "file" (i - 2) ".txt";
print $1, $2, $i >> fn;
}
}' inputfile
也就是说,当你在第一个记录, 写标题行和空行(如在你的问题中指定)创建输出文件。
对于第3个及以后的记录,附加到文件。
请注意,您的问题中的代码表明该文件中的字段由制表符分隔,但示例文件似乎使用填充了可变数量空格的|
。目前还不清楚哪一个是你的实际案例。如果它真的是制表符分隔的,那么上面的代码就可以工作。如果实际上它是作为例子输入,则第一行改成这样:
awk -v OFS=' | ' -v FS='[ |]+' '
Hi Janos,你可以给你的邮件ID。我想向你展示我的原始需求。 @janos –
嗨@ArunVenkitusamy,我宁愿不。如果您的真实需求与您的问题不同,那是非常不幸的,我希望您先写下。问问题,得到答案,然后将问题改为其他问题是不公平的。如果需要稍作澄清,请编辑您的问题,也许我们可以提供帮助。如果你需要不同的东西,最好问一个新问题。 – janos
嗨@janos,对不起,浪费你的时间..我创造了一个新的问题。请看看[http://*.com/questions/43965359/awk-or-shell-script-to-change-format-of-a-tab-delimited-file] –
的bash + 切溶液:
input.tsv试验内容:
Code | Name | Day1 | Day2 | Day3
10001 | abcd | 5 | 1 | 9
10002 | degg | 3 | 9 | 6
10003 | gxyz | 4 | 8 | 7
day_splitter。SH脚本:
#!/bin/bash
n=$(cat $1 | head -1 | awk -F'|' '{print NF}') # total number of fields
for ((i=3; i<=$n; i++))
do
fn="Day"$(($i-2)) # file name containing `Day` number
$(cut -d'|' -f1,2,$i $1 > $fn".txt")
done
用法:
bash day_splitter.sh input.tsv
结果:
$cat Day1.txt
Code | Name | Day1
10001 | abcd | 5
10002 | degg | 3
10003 | gxyz | 4
$cat Day2.txt
Code | Name | Day2
10001 | abcd | 1
10002 | degg | 9
10003 | gxyz | 8
$cat Day3.txt
Code | Name | Day3
10001 | abcd | 9
10002 | degg | 6
10003 | gxyz | 7
在纯AWK:
$ awk 'BEGIN{FS=OFS="|"}{for(i=3;i<=NF;i++) {f="file" (i-2); print $1,$2,$i >> f; close(f)}}' file
解释:
$ awk '
BEGIN {
FS=OFS="|" } # set delimiters
{
for(i=3;i<=NF;i++) { # loop the consumption fields
f="file" (i-2) # create the filename
print $1,$2,$i >> f # append to target file
close(f) } # close the target file
}' file
你混合壳和awk。 ..单独使用awk .. https://www.gnu.org/software/gawk/manual/html_node/For-Statement.html – Sundeep
对不起,我不知道区分awk和shell。如果可能,请直接告诉我代码以获取该输出。 @Sundeep –
看看早先评论中的文档链接的语法...你只需要将其移动到awk中的循环中...试试看吧 – Sundeep