我的输入 File1 如下所示:
A,22,1,2,3,4,5
G,26,5,6,7
X,28,10,20,10
我想在保持文件结构的同时将方程应用于第 3 列。例如,如果我想要使用的方程乘以 2,我正在寻找输出:
A,22,2,4,6,8,10
G,26,10,12,14
X,28,20,40,20
我尝试使用以下命令来执行此操作:
awk -F ',' '{for(i=1; i<=NF; i++) if (i >= 3)
print 2*$i
else
print $i }' File1
这提供了正确的输出,但消除了所有文件结构。如果使用我想要使用的实际方程是: 2*(2*($i-1)+1)
非常感谢解决方案附带的任何解释,因为我对此仍然很陌生!
答案1
您只需设置输出字段分隔符(OFS
),例如:
awk '{ for (i=3; i<=NF; i++) $i*=2 } 1' FS=, OFS=, infile
或者使用你的公式:
awk '{ for (i=3; i<=NF; i++) $i = 2*(2*($i-1)+1) } 1' FS=, OFS=, infile
输出:
A,22,2,4,6,8,10
G,26,10,12,14
X,28,20,40,20
脚本末尾的1
是以下内容的简写{ print $0 }
答案2
Perl
可以解决如下所示:基于@Thor的建议:
$ perl -F, -anE '$,="," ; say splice(@F,0,2), map { 2*(2*($_-1)+1) } @F' inp.csv
使用另一种方法:
$ perl -lpe '
/^[^,]*,[^,]*/g; #positions the search engine before the 2nd comma.
s/\G,\K([^,]*)/2*(2*($1-1)+1)/ge;
' inp.csv
GNU 桌面计算器实用程序可以执行以下操作:
$ < inp.csv tr ',-' ' _' | sed -Ee 's/\S+/[&]/' |
dc -e "
[q]sq
[44an]s,
[1-2*1+2*]s=
[SM lN1+sN z0<a]sa
[LMnl,x LMnl,x lN2-sN]sb
[LMl=xn lN1<, lN1-dsN0<c]sc
[?z0=q 0sN lax lbx lcx 10an z0=?]s?
l?x
"
这些是简单的实用程序和根据要求进行的解释,因为这些是简单明了的代码。
简要说明:
该dc
实用程序在堆栈上工作,在堆栈上存储数据和代码。从这里开始,它将 n 个检索存储在寄存器中。
字符串数据用方括号括起来。
删除是通过递归完成的。
在这个dc代码中有7个寄存器存储代码,即q = , abc ?
两个寄存器MN存储数据。
从最后开始倒推。代码寄存器?执行从输入读取下一行的操作。然后比较其堆栈上有多少个空格分隔的项目;将它们视为字段。如果是 0 ,则停止 n 退出。 z0=q 片段就是这样做的。它的读法是: z 是返回存在元素数量的 dc 命令。我们与 0 进行比较,如果相等,则执行寄存器 q 中存储的代码。
答案3
s=`awk '{print NR}' p.txt| sort -nr | sed -n '1p'`
praveen@praveen:~$ for ((i=1;i<=$s;i++)); do m=`awk -v i="$i" -F "," 'NR==i{print NF}' p.txt`; for ((u=1;u<=$m;u++)); do if [[ $u < 3 ]]; then awk -v i="$i" -v u="$u" -F "," 'NR==i{print $u}' p.txt; else awk -v i="$i" -v u="$u" -F "," 'NR==i {print 2*$u}' p.txt; fi; done| sed "N;s/\n/,/g"| sed "N;s/\n/,/g"| sed "N;s/\n/,/g"; done
where p.txt is filename
A,22,2,4,6,8,10
G,26,10,12,14
X,28,20,40,20