【问题标题】:reformat list string with spaces用空格重新格式化列表字符串
【发布时间】:2021-04-01 19:38:08
【问题描述】:

我有一个打印到控制台的字符串列表。我需要将其转换回带引号的字符串。

假设示例文件如下所示

List(UT_LVL_17_CD, UT_LVL_20_CD, 2018 1Q, 2018 2Q, 2018 3Q, 2018 4Q, 2018 FY)
List(UT_LVL_17_CD,UT_LVL_20_CD,2018 1Q,2018 2Q,018 3Q,2018 4Q,2018 FY)
List( UT_LVL_17_CD,    UT_LVL_20_CD,2018 1Q,2018 2Q, 2018 3Q, 2018 4Q, 2018 FY )

对于上述所有 3 种组合,输出应为

List("UT_LVL_17_CD", "UT_LVL_20_CD", "2018 1Q", "2018 2Q", "2018 3Q", "2018 4Q", "2018 FY")

请注意,开始、结束或元素之间的空格是可以接受的。

List(  "UT_LVL_17_CD", "UT_LVL_20_CD", "2018 1Q", "2018 2Q", "2018 3Q", "2018 4Q",    "2018 FY" )

但不在字符串值内,如下所示

"     UT_LVL_17_CD"
"UT_LVL_20_CD   ",

应该保留每个元素中已有的空格"2018 4Q"

我正在尝试类似下面的方法,但无法获得正确的结果。

$ perl -pe ' s/(?<=\()|(?=,)|(?=\))/\"/sg ' list.txt
List("UT_LVL_17_CD", UT_LVL_20_CD", 2018 1Q", 2018 2Q", 2018 3Q", 2018 4Q", 2018 FY")
List("UT_LVL_17_CD",UT_LVL_20_CD",2018 1Q",2018 2Q",018 3Q",2018 4Q",2018 FY")
List(" UT_LVL_17_CD",    UT_LVL_20_CD",2018 1Q",2018 2Q", 2018 3Q", 2018 4Q", 2018 FY ")
$

【问题讨论】:

标签: regex perl awk


【解决方案1】:

试试这个

(?<=\(|,)\s*(.*?)\s*(?=\)|,)

通过这个正则表达式,您可以将每个文本与开头和结尾不包含空格的组匹配,然后附加到它“”
look at demo

【讨论】:

    【解决方案2】:
    perl -wpe'
        s{ \(\K ([^)]+) }
         { join ", ", map { s/^\s+|\s+$//g; qq("$_") } split /,/, $1 }ex
    ' file
    

    【讨论】:

    • 最后一个值显示为"2018 FY ",应该是"2018 FY"
    • @stack0114106 已修复。没有什么比简单地去除 map 中的前导/尾随空格更好的了,稍后再看...
    • np.. 祝你有美好的一天
    • 编辑:必须删除map 中的尾随空格——但随后可以全部清除,因此删除了其他\s
    【解决方案3】:

    看看以下是否适合你:

    [(,]\K\s*(.*?)\s*(?=[),])
    

    在线查看demo


    • [(,] - 匹配逗号或左括号。
    • \K - 重置报告匹配的起点。
    • \s* - 匹配零个或多个空格。
    • (.*?) - 第一个捕获组使用惰性量词捕获任何字符。
    • \s* - 匹配零个或多个空格。
    • (?=[),]) - 正向前瞻以匹配逗号或右括号。

    根据链接的演示,替换为"\1"

    【讨论】:

      【解决方案4】:

      另一种选择是使用\G 锚点并匹配可选地由空格和单词字符重复的单词字符。

      (?:\G(?!^),|\bList\((?=[^()\r\n]*\)))\K\h*(\w+(?:\h+\w+)*)\h*
      

      说明

      • (?:非捕获组
        • \G(?!^), 在上一场比赛结束时断言位置,而不是在开始时(因为\G 可以匹配这两个位置)
        • |或者
        • \bList\((?=[^()\r\n]*\)) 字边界,然后匹配 List( 并在同一行断言结束 )
      • )关闭非捕获组
      • \K\h* 忘记到目前为止匹配的内容(不删除匹配的List( 和逗号)并匹配要删除的可选空格
      • ( 捕获第一组
        • \w+(?:\h+\w+)* 匹配 1+ 个单词字符,可选地由空格和单词字符重复
      • )\h* 关闭第 1 组并匹配要删除的可选尾随空格

      Regex demo

      在双引号"\1"之间替换使用组1

      【讨论】:

      【解决方案5】:

      又一个变种:

      $ perl -pne 's/\(\s+/\(/; /([^(]+\()(.+)\)/; $_="$1\"".join("\",\"",split(/,\s*/,$2)).")\n"; ' file
      List("UT_LVL_17_CD","UT_LVL_20_CD","2018 1Q","2018 2Q","2018 3Q","2018 4Q","2018 FY)
      List("UT_LVL_17_CD","UT_LVL_20_CD","2018 1Q","2018 2Q","018     3Q","2018 4Q","2018 FY)
      List("UT_LVL_17_CD","UT_LVL_20_CD","2018 1Q","2018 2Q","2018 3Q","2018 4Q","2018 FY )
      

      输入测试文件:

      $ cat file
      List(UT_LVL_17_CD, UT_LVL_20_CD, 2018 1Q, 2018 2Q, 2018 3Q, 2018 4Q, 2018 FY)
      List(UT_LVL_17_CD,    UT_LVL_20_CD,2018 1Q,2018 2Q,018     3Q,2018 4Q,2018 FY)
      List( UT_LVL_17_CD,    UT_LVL_20_CD,2018 1Q,2018 2Q, 2018 3Q, 2018 4Q, 2018 FY )
      

      【讨论】:

      • 伟大的..idea.. 在初始清理后在/,\s*/ 上拆分..
      【解决方案6】:

      OP 提到前导/尾随空格是可以接受的……我认为这意味着去掉不必要的前导/尾随空格也是可以接受的。

      示例输入:

      $ cat string.dat
      List(UT_LVL_17_CD, UT_LVL_20_CD, 2018 1Q, 2018 2Q, 2018 3Q, 2018 4Q, 2018 FY)
      List(UT_LVL_17_CD,UT_LVL_20_CD,2018 1Q,2018 2Q,018 3Q,2018 4Q,2018 FY)
      List( UT_LVL_17_CD,    UT_LVL_20_CD,2018 1Q,2018 2Q, 2018 3Q, 2018 4Q, 2018 FY )
      

      一个不太紧凑的awk 想法:

      awk -F'[()]' '                         # input field delimiters are "(" and ")"
      { printf "%s(", $1                     # print field #1 + "("
        n=split($2,a,",")                    # split field #2 by ",", save in array a[]
        pfx=""                               # initial prefix is ""
        for (i=1 ; i<=n ; i++)               # loop through a[] elements
            { gsub(/^ *| *$/,"",a[i])        # strip leading/trailing spaces
              printf "%s\"%s\"", pfx, a[i]   # print prefix + current a[] element wrapped in double quotes
              pfx=","                        # set prefix to "," for rest of a[] elements
            }
         printf ")\n"                        # print final ")"
      }
      ' string.dat
      

      这会生成:

      List("UT_LVL_17_CD","UT_LVL_20_CD","2018 1Q","2018 2Q","2018 3Q","2018 4Q","2018 FY")
      List("UT_LVL_17_CD","UT_LVL_20_CD","2018 1Q","2018 2Q","018 3Q","2018 4Q","2018 FY")
      List("UT_LVL_17_CD","UT_LVL_20_CD","2018 1Q","2018 2Q","2018 3Q","2018 4Q","2018 FY")
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-20
        • 1970-01-01
        • 1970-01-01
        • 2017-03-31
        • 2016-06-27
        • 1970-01-01
        相关资源
        最近更新 更多