Awk 使用SED替换括号中的特定模式?

Awk 使用SED替换括号中的特定模式?,awk,sed,grep,text-processing,Awk,Sed,Grep,Text Processing,我对这个有点问题。。。 我试图使用Bash脚本(特别是Sed)来处理以下文本。当然,也欢迎使用其他方法!但我希望这是一个Bash解决方案 棘手的输入: ("a"|"b"|"c")."A"|"B"|"C".("e"|"f")."E"|"F" 期望输出: ("a"|"b&

我对这个有点问题。。。 我试图使用Bash脚本(特别是Sed)来处理以下文本。当然,也欢迎使用其他方法!但我希望这是一个Bash解决方案

棘手的输入:

("a"|"b"|"c")."A"|"B"|"C".("e"|"f")."E"|"F"
期望输出:

("a"|"b"|"c")."ABC".("e"|"f")."EF"
主要是,我想我要做的是什么都不替换字符串
“|”
,但将更改范围限制在括号中现有文本之外

问题变得更加疯狂,因为我有不同形式的文本输入和数据集。与中一样,带有括号和非括号的块(由
分隔)的组合也是不同的

提前谢谢


我用SED做了一些尝试:

gsed -E "s/(\.\"[[:graph:]]+)\"\|\"/\1/g" input.txt
我得到的结果是:

("a"|"b"|"c")."A"|"B"|"C".("e"|"f")."EF"

看起来我只获得了部分所需的输出…仅针对有限的范围…

请尝试以下操作:

#!/bin/bash

awk 'BEGIN {FS = OFS = "."}                     # use "." as a field separator
{
    for (i = 1; i <= NF; i++) {                 # loop over the fields
        if ($i !~ "^\\(.+\\)$") {               # if the fields is not enclosed with "(" and ")"
            gsub("\"\\|\"", "", $i)             # then remove "|"s
        }
    }
    print
}' <<< '("a"|"b"|"c")."A"|"B"|"C".("e"|"f")."E"|"F"'
[解释]

  • BEGIN{}
    块在处理输入之前只执行一次 文件初始化变量很有用
  • 当awk变量
    FS
    被分配给“.”时, 输入行将自动 在“”上拆分。然后,
    $1
    被分配给第一个字段
    (“a”|“b”|“c”)
    $2
    分配给第二个
    “A”|“B”|“C”
    。。等等awk变量
    NF
    设置为字段数(本例中为4)

  • for循环
    for(i=1;i假设/理解:

    • 字段由句点分隔
    • 用帕伦包装的字段将被单独保留
    • 所有其他字段都有前导/尾随双引号,而所有其他双引号以及管道都将被删除
    样本数据:

    $ cat pipes.dat
    ("a"|"b"|"c")."A"|"B"|"C".("e"|"f")."E"|"F"
    "j"|"K"|"L"."m"|"n"|"o"|"p".("x"|"y"|"z")
    
    一个
    awk
    idea:

    awk '
    BEGIN { FS=OFS="." }                                      # define input/output field separator as a period
    
          { printf "############\nbefore: %s\n",$0            # print a record separator and the current input line;
                                                              # solely for display purposes; this line can
                                                              # be removed/commented-out once logic is verified
    
            for (i=1; i<=NF; i++)                             # loop through fields
                if ( $i !~ "^[(].*[)]$" )                     # if field does not start/end with parens then ...
                    $i="\"" gensub(/"|\|/,"","g",$i) "\""     # replace field with a new double quote (+) modified string
                                                              # whereby all double quotes and pipes are removed (+)
                                                              # a new ending double quote
    
            printf "after : %s\n",$0                          # print the newly modified line;
                                                              # can be replaced with "print" once logic is verified
          }
    ' pipes.dat                                               # read data from file; to read from a variable remove this line and ...
    #' <<< "${variable_name}"                                 # uncomment this line
    

    删除注释并进行
    printf
    更改后:

    awk '
    BEGIN { FS=OFS="." }
          { for (i=1; i<=NF; i++)
                if ( $i !~ "^[(].*[)]$" )
                    $i="\"" gensub(/"|\|/,"","g",$i) "\"" 
            print
          }
    ' pipes.dat
    

    决定操作的顺序,它可能是可解的。括号是用来保护其中包含的内容,还是为什么不能折叠成“ABC”、“ABC”、“EF”?您好,不确定您所说的“为什么不能折叠成…”是什么意思。目的是防止替换
    “|”
    存在于parens中,同时对不在parens中的文本执行此操作。谢谢,这回答了我的问题:“括号是否保护了其中包含的内容?”。根据您看到的操作顺序制作一个表格,然后用笔和纸进行计算。如果无法进行计算,则尝试对其进行编程将有问题。为了便于讨论…字符组之间以句点(
    )分隔;是否所有奇数字段都用paren包装?偶数字段没有paren?您提到了
    sed
    …请使用您尝试过的
    sed
    命令和(错误)更新问题结果他们生成了带括号的字符组,这些字符可以出现在不同的地方,而不仅仅出现在奇数字段中……完全是可选的,以及“字段”的总数不是固定的。这很好。谢谢你的回答。我会对AWK做一些研究。虽然你可能会得到一个
    sed
    解决方案来工作,但我想你会发现这些
    AWK
    解决方案会更容易理解(如果输入格式发生变化,也更容易修改)这是一个新手,所以也要考虑复习,好运气。谢谢你的回答。我会做一些关于AWK的研究。谢谢你的反馈。我增加了一些代码的解释,希望能帮助你学习。
    ############
    before: ("a"|"b"|"c")."A"|"B"|"C".("e"|"f")."E"|"F"
    after : ("a"|"b"|"c")."ABC".("e"|"f")."EF"
    ############
    before: "j"|"K"|"L"."m"|"n"|"o"|"p".("x"|"y"|"z")
    after : "jKL"."mnop".("x"|"y"|"z")
    
    awk '
    BEGIN { FS=OFS="." }
          { for (i=1; i<=NF; i++)
                if ( $i !~ "^[(].*[)]$" )
                    $i="\"" gensub(/"|\|/,"","g",$i) "\"" 
            print
          }
    ' pipes.dat
    
    ("a"|"b"|"c")."ABC".("e"|"f")."EF"
    "jKL"."mnop".("x"|"y"|"z")