如何将存储的值作为列号参数传递以在 awk 中进行编辑?
Posted
技术标签:
【中文标题】如何将存储的值作为列号参数传递以在 awk 中进行编辑?【英文标题】:How do I pass a stored value as the column number parameter to edit in awk? 【发布时间】:2016-07-05 16:41:17 【问题描述】:我有一个带有|
分隔符的 .dat 文件,我想更改由作为参数传递并存储在 var 中的数字定义的列的值。我的代码是
awk -v var="$value" -F'|' ' FS = OFS = "|" $1=="$id" $"\$var"=81'
myfile.dat > tmp && mv tmp myfiletemp.dat
这会将整行更改为 8,显然不起作用。我想知道写这部分的正确方法是什么
$"\$var"=81
例如,如果我想将第四列更改为 8,并且我有value=4
,我如何获得$4=8
?
【问题讨论】:
更改第一列(1作为变量传入):echo foo bar baz | awk '$v=k1' k=qux v=1
v 从存储的变量 v="$var" 中获取一个值,当我使用此方法时,整行变为 1
无论您一直在使用什么来尝试学习 awk,都将其扔掉,并获得 Arnold Robbins 的《Effective Awk Programming, 4th Edition》一书,因为您目前对 awk 语法和语义感到非常困惑。
我看东西,我没有研究任何关于 awk 的书,请原谅我。我找到了解决方案
【参考方案1】:
另一个答案大部分是正确的,但只是想添加一些注释,以防不完全清楚。
-
引用前面带有
$
的变量会将其转换为对列的引用。所以i=3; print $i; print i
将打印第三列,然后是数字 3。
将所有变量放在命令行中可以避免尝试在单引号 awk
代码中包含 bash
变量时出现任何问题,但这是行不通的。
您可以让awk
输出到特定文件,而不是依赖 bash 来重定向输出和移动文件。
命令行中的-F
选项为您指定FS
,因此无需在您的代码中重新声明它。
我会这样做:
#!/bin/bash
column=4
value=8
id=1
awk -v col="$column" -v val="$value" -v id="$id" -F"|" '
BEGIN OFS="|"
$1==id && $col=val; print > "myfiletemp.dat"
' myfile.dat
【讨论】:
请注意这不是惯用的awk
。除非您有充分的理由(文件名取决于字段、拆分文件等),否则您不会在脚本中打印到文件名。 awk
鼓励条件action 块,应该写成... $1==id$col=val1'. There is no point of setting OFS at each loop, either set with
-v OFS` 或BEGIN
块。
@karakfa 谢谢我的意思是让第一个代码块成为BEGIN
(这就是为什么它是一个单独的块!)【参考方案2】:
您可以通过名称直接引用 awk 变量,稍微重写脚本并正确引用列号 var...
awk -F'|' -v var="$value" 'BEGINOFS=FS $1=="$id"$var=81'
只要 $value 是一个数字就应该可以工作。如果id
是另一个 bash 变量,则以与 awk 变量相同的方式传递它
awk -F'|' -v var="$value" -v id="$id" 'BEGINOFS=FS $1==id$var=81'
【讨论】:
Bash 变量$id
不会在单引号内得到解释。
OP $id 中的 似乎不是一个变量。我以为这是文字。
你就是这样做的,是的。在看到您的回复之前我已经尝试过了,并且成功了,就是这样,谢谢。【参考方案3】:
不仅可以通过在变量前面加上$
来在变量中使用数字,还可以在表达式前面加上$
!
$ date | tee /dev/stderr | awk 'print $(2+2)'
Mon Aug 3 12:47:39 CDT 2020
12:47:39
【讨论】:
以上是关于如何将存储的值作为列号参数传递以在 awk 中进行编辑?的主要内容,如果未能解决你的问题,请参考以下文章