首页
学习
活动
专区
圈层
工具
发布

awk
EN

Unix & Linux用户
提问于 2020-02-07 08:02:25
回答 3查看 523关注 0票数 1

我们有一个1.5MB文件。每一行大约有160000个字符。在行中,我们需要将"false“转换为"true”,只需在模式结束后立即进行一次。

跟随awk只会第一次发生变化。但我们只需要在“模式”之后改变一次。

代码语言:javascript
复制
awk '/PATTERN.*false/ {sub("false", "true")} {print}' file

我们的文件包括:

代码语言:javascript
复制
...
colorA is false colorB is false PATTERN is false colorC is false colorD is false
...

文件需要有:

代码语言:javascript
复制
...
colorA is false colorB is false PATTERN is true colorC is false colorD is false
...

我们如何安排awk命令来满足我们的需要?

提前谢谢!

EN

回答 3

Unix & Linux用户

回答已采纳

发布于 2020-02-07 08:42:49

虽然在理论上可以编写一个与不匹配"false“的最短字符串匹配的正则表达式,但这是很困难的。其他各种语言都可以选择最短的语法,但awk不是其中之一。

因此,有3种方法可以使用,假设您不想编写硬表达式。

  1. 您可以在单词"false“上拆分输入,在字段上循环,如果当前字段与模式匹配,则将其打印出来,后面跟着"true",否则将其打印出来,后面跟着"false”。
  2. 您可以使用一个技巧,将所有出现的"false“转换为一个单独的未使用的字符,如control-a,那么正则表达式很容易编写,因为您可以说*\001来匹配以控制-a结尾的最短模式。
  3. 您只需在字段上循环,如果当前字段是您的模式,则设置一个标志,如果设置为"false“,并且设置了标志,则将其更改为"true”并重置标志。

第三条路。

代码语言:javascript
复制
#!/usr/bin/awk

/PATTERN.*false/ {
        for(i=1;i<=NF;i++) {
                if ($i ~ /PATTERN/) flag=1;
                if ($i == "false" && flag==1) {
                        $i="true"
                        flag=0
                }
        }
}
{print}

这将折叠输入中的空白。

票数 1
EN

Unix & Linux用户

发布于 2020-02-07 09:06:25

该解决方案实现了在PATTERN (split)处拆分行的方法,替代了第二部分(sub)中的第一个false,并结合了各个部分(for循环和printf)。next命令跳过此输入行的进一步处理。其他行则不作改动。(1是具有默认操作的始终为真的条件。)

代码语言:javascript
复制
awk '/PATTERN.*false/ {
    n=split($0,parts,"PATTERN"); 
    sub("false", "true", parts[2]); 
    for(i=1;i

与PATTERN相对应的值是否总是false并不清楚,因此它可能会替换错误的false。

样本输入

代码语言:javascript
复制
colorA is false colorB is false PATTERN is false colorC is false colorD is false
colorA is false colorB is false PATTERN is true colorC is false colorD is false

这一产出的结果

代码语言:javascript
复制
colorA is false colorB is false PATTERN is true colorC is false colorD is false
colorA is false colorB is false PATTERN is true colorC is true colorD is false

编辑根据RudiC's的评论:如果在模式后要修改的值为"true“或"false",则可以通过将指令sub("false", "true", parts[2]);替换为sub("false|true", "true", parts[2]);来避免这个可能的问题。

代码语言:javascript
复制
awk '/PATTERN.*false/ {
    n=split($0,parts,"PATTERN"); 
    sub("false|true", "true", parts[2]); 
    for(i=1;i

使用相同的示例输入,这将导致

代码语言:javascript
复制
colorA is false colorB is false PATTERN is true colorC is false colorD is false
colorA is false colorB is false PATTERN is true colorC is false colorD is false
票数 0
EN

Unix & Linux用户

发布于 2020-02-07 22:52:55

使用GNU awk来匹配()和gensub():

代码语言:javascript
复制
$ awk 'match($0,/(.*PATTERN)(.*)/,a){$0=a[1] gensub(/false/,"true",1,a[2])} 1' file
...
colorA is false colorB is false PATTERN is true colorC is false colorD is false
...

对任何一只鹰来说:

代码语言:javascript
复制
$ awk 'match($0,/.*PATTERN/){tail=substr($0,RSTART+RLENGTH); sub(/false/,"true",tail); $0=substr($0,1,RSTART+RLENGTH-1) tail } 1' file
...
colorA is false colorB is false PATTERN is true colorC is false colorD is false
...
票数 0
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/566261

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档