awk,如果记录包含值则为条件 [英] awk, if else conditional when record contains a value

查看:146
本文介绍了awk,如果记录包含值则为条件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当记录包含值时,我很难获得awk if/else条件,以正确触发.在Mac OS Catalina上的zsh中运行此程序.

I'm having trouble getting an awk if/else conditional to properly trigger when the record contains a value. Running this in zsh on Mac OS Catalina.

此脚本(问题在倒数第二行)...

This script (issue is on second to last line)...

echo "abcdefgh" >  ./temp
echo "abc\"\(\"h" >> ./temp
echo "abcdefgh" >> ./temp
echo "abcde\(h" >> ./temp 

val='"\("'
key="NEW_NEW"
file="./temp"

echo $val
echo $key
echo $file

echo ""
echo "###############"
echo ""

awk '
    BEGIN { old=ARGV[1]; new=ARGV[2]; ARGV[1]=ARGV[2]=""; len=length(old) }
    ($0 ~ /old/){ s=index($0,old); print substr($0,1,s-1) new substr($0,s+len) }{ print $0 }
' $val $key $file

输出:

"\("
NEW_NEW
./temp

###############

abcdefgh
abc"\("h
abcdefgh
abcde\(h

我想修复脚本,以便将"\("更改为NEW_NEW,但是跳过不带引号的括号...

I want to fix the script so that it changes the "\(" to NEW_NEW but skips the parenthesis without the quotes...

"\("
NEW_NEW
./temp

###############

abcdefgh
abcNEW_NEWh
abcdefgh
abcde\(h

编辑

这是我正在处理的真实脚本的缩写版本.答案将需要包含上面的示例所具有的变量扩展,以便我在较大的脚本中使用该命令.正在使用的ARGV格式保留了特殊字符,因此,我遇到的主要问题是为什么条件没有如预期那样触发.

This is an abbreviated version of the real script that I'm working on. The answer will need to include the variable expansions that the sample above has, in order for me to use the command in the larger script. The ARGV format in use is preserving special characters, so the main question I have is why the conditional isn’t triggered as expected.

推荐答案

($0 ~ /old/)的意思是在当前记录($0)和文字regexp old之间进行regexp比较",因此当$ 0包含old依次为3个字符.您可能正在尝试对名为$0 ~ old的变量old的内容进行正则表达式比较(请参阅 https://stackoverflow.com/a/62096075/1745001 所示),但是您有现在出于某种原因移出了condition { action } awk语句的条件部分,并将其作为操作的第一部分.所以不要那样.

($0 ~ /old/) means "do a regexp comparison between the current record ($0) and the literal regexp old" so it matches when $0 contains the 3 characters o, l, d in that order. You probably were trying to do a regexp comparison against the contents of the variable named old which would be $0 ~ old (see How do I use shell variables in an awk script?) but you don't actually want that, you want a string comparison which would be index($0,old) as shown in your previous question (https://stackoverflow.com/a/62096075/1745001) but which you have now for some reason moved out of the condition part of your condition { action } awk statement and put it as the first part of the action instead. So don't do that.

脚本的另一个主要问题是您要删除外壳变量周围的引号,以便它们被外壳解释并经过遍历,扩展文件名等操作,甚至在awk之前都无法看到它们(请参见 https://mywiki.wooledge.org/Quotes ).所以也不要这样做.

The other major problem with your script is you're removing the quotes from around your shell variables so they're being interpreted by the shell and undergoing globbing, file name expansion, etc. before awk even gets to see them (see https://mywiki.wooledge.org/Quotes). So don't do that either.

只修复我提到的部分:

$ cat tst.sh
echo "abcdefgh" >  ./temp
echo "abc\"\(\"h" >> ./temp
echo "abcdefgh" >> ./temp
echo "abcde\(h" >> ./temp

val='"\("'
key="NEW_NEW"
file="./temp"

echo "$val"
echo "$key"
echo "$file"

echo ""
echo "###############"
echo ""

awk '
    BEGIN { old=ARGV[1]; new=ARGV[2]; ARGV[1]=ARGV[2]=""; len=length(old) }
    s=index($0,old) { $0 = substr($0,1,s-1) new substr($0,s+len) }
    { print }
' "$val" "$key" "$file"

.

$ ./tst.sh
"\("
NEW_NEW
./temp

###############

abcdefgh
abcNEW_NEWh
abcdefgh
abcde\(h

这篇关于awk,如果记录包含值则为条件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆