如何使用awk
查找和替换特定列的值?
例如->我有一个文件测试,内容如下:
“ abc”:“ 100” ::“新”
“ xyz”:“ 200”:“暴徒”:“旧”
“ lmn”:“ 300” ::“新”
“ pqr”:“ 400”:“ mob2”:“新”
现在,如果第3列为空白,那么我想替换"N/A"
中的空白值,否则按原样打印该行,以便输出如下:
“ abc”:“ 100”:“ N / A”:“新”
“ xyz”:“ 200”:“暴徒”:“旧”
“ lmn”:“ 300”:“ N / A”:“新”
“ pqr”:“ 400”:“ mob2”:“新”
尽管我通过以下命令使用awk获得了输出:
awk -F":" '{
if ( $3 == "")
print $1":"$2":\"N\/A\":"$4
else
print $0
}' test
但是这里我为每一列使用硬编码值,例如$1
,$2
,因此如果空白列在其他示例中从3rd更改为xyz,则必须再次在命令中更改相同的值。还有其他方法可以使用awk且不对列使用硬编码值来获得相同的输出吗?感谢您的帮助。
答案 0 :(得分:1)
首先,让我们简化一下您当前的程序:
awk -F: 'BEGIN {OFS=FS} {
if ( $3 == "") $3="N/A"
print $0
}' test
现在,我们可以使两件事可变:要测试的列和替换字符串。因此,程序的主体将类似于
if ( $fieldnumber == "" ) $fieldnumber=replacement
剩下要做的是填写变量。如果查看awk的手册页,就会发现选项-v
允许我们为awk变量指定初始值。
awk -F: -v fieldnumber=... -v replacement=...
这使您可以从任意位置填充此变量-Shell脚本的参数,环境变量等。
更新:修复输出字段分隔符(OFS) 更新:修复语法错误
答案 1 :(得分:1)
使用GNU awk for FPAT和修改后的输入文件来证明正确的方法,即使引号字段中存在冒号也是如此:
$ cat tst.awk
BEGIN {
FPAT = "([^:]*)|(\"[^\"]+\")"
OFS = ":"
}
$3 == "" { $3 = "\"N/A\"" }
{ print }
$ cat file
"abc:def":"100"::"new"
"xyz":"200":"mob":"old"
"lmn":"123:456:300"::"new"
"pqr":"400":"mob2":"new"
"stu":"600":"foo::bar":"more"
$ awk -f tst.awk file
"abc:def":"100":"N/A":"new"
"xyz":"200":"mob":"old"
"lmn":"123:456:300":"N/A":"new"
"pqr":"400":"mob2":"new"
"stu":"600":"foo::bar":"more"
答案 2 :(得分:0)
使用GNU awk:
awk -v RS='[:\n]' '!NF{$0="\"N/A\""}{printf "%s%s",$0,RT}' test
记录分隔符RS
设置为捕获分号:
之间的数据。
如果没有任何字段(!NF
),则设置所需的字符串。
printf语句为当前记录写入数据和记录分隔符RT
。
答案 3 :(得分:0)
下面的gawk代码怎么样:
BEGIN {
FS=":"
OFS=":"
}
{
for(i=1; i<=4; i++) {
if ($(i) == "") field[i] = "N/A"
else field[i] = $(i)
}
if ($0 != "") print field[1],field[2],field[3],field[4]
}
-或-
也许下面的bash脚本要简单得多:
#!/bin/bash
export IFS=":"
while read a b c d; do
echo "${a:-N/A}:${b:-N/A}:${c:-N/A}:${d:-N/A}"
done
具有输入重定向,即this_bash_script.sh < your_test_input.txt