如果找到,使用awk替换特定的列值

时间:2018-07-10 06:08:49

标签: bash shell awk scripting

如何使用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且不对列使用硬编码值来获得相同的输出吗?感谢您的帮助。

4 个答案:

答案 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