替换特定字符,但如果它在 () 内部则不替换

替换特定字符,但如果它在 () 内部则不替换

我正在寻找一个单行命令来使文件更具可读性。我想将所有;字符替换为 ,newline除非它位于一组().这是在防火墙上,所以我只能使用 bash;没有perl等。

输入示例:

ProductName: Threat Emulation; product_family: Threat; Destination: (countryname: United States; IP: 127.0.0.1; repetitions: 1) ; FileName: (file_name: myfile) ;

预期输出:

ProductName: Threat Emulation
product_family: Threat
Destination: (countryname: United States; IP: 127.0.0.1; repetitions: 1)
FileName: (file_name: myfile)

答案1

sed 的正则表达式有点令人困惑,但可行

sed '
    :a                                                 #mark return point
    s/\(\(^\|)\)[^(]\+\);\s*\([^)]\+\((\|$\)\)/\1\n\3/ #remove ; between ) and (
    ta                                                 #repeat if substitute success
    s/[[:blank:];]\+$//                                #remove ; with spaces at end
    '

Breif正则表达式解释:

  • ^\|)从行开始或)
  • [^(]\+任何符号,但(
  • ;\s*带有可能空格的分号
  • (\|$直到行尾或(

答案2

如果您有 awk,则可以使用括号作为字段分隔符:

awk -F '[()]' '{
    for (i=1; i<=NF; i+=2) {
        if ($i) {
            gsub(/; */,"\n",$i)
            printf "%s", $i
            if ($(i+1)) printf "(%s)", $(i+1)
        }
    }
    print ""
}' <<END
ProductName: Threat Emulation; product_family: Threat; Destination: (countryname: United States; IP: 127.0.0.1; repetitions: 1) ; FileName: (file_name: myfile) ;
END
ProductName: Threat Emulation
product_family: Threat
Destination: (countryname: United States; IP: 127.0.0.1; repetitions: 1) 
FileName: (file_name: myfile) 

尾随分号为您提供尾随换行符。

相关内容