【问题标题】:Text processing - Split the first column into two columns based on a character文本处理 - 根据一个字符将第一列分成两列
【发布时间】:2019-10-19 21:59:06
【问题描述】:

根据一个字符将文件中的第一列分成两列。 括号 () 内的数据应移至删除括号的新列。

给定 csv 文件:

Col1(col2),col3,col4,col5
a(23),12,test(1),test2
b(30),15,test1(2),test3

预期文件:

Col1,col2,col3,col4,col5
a,23,12,test(1),test2
b,30,15,test1(2),test3

我尝试了以下代码。我无法提取括号之间的数据,而且每次出现“()”。

awk -F"(" '$1=$1' OFS="," filename

【问题讨论】:

  • awk -F"[(),]+" '$1=$1' OFS="," file?
  • @WiktorStribiżew 仅在您需要时使用操作的结果作为条件,否则您会混淆代码并引入潜在的错误。在这种情况下,例如,当 $10 时,您的脚本将失败 - 写入 {$1=$1}1 而不仅仅是 $1=$1
  • @EdMorton 我没有写它:) 它是复制/粘贴。我只关注字段分隔符模式。
  • @WiktorStribiżew 对我来说,你没有提出一个完整的解决方案并不明显,所以 OP 可能也没有意识到这一点。

标签: shell awk sed text-processing cut


【解决方案1】:

您能否再尝试 1 个sed 解决方案,这可能会对您有所帮助。

sed 's/\([^(]*\)(\([^)]*\))\(.*\)/\1,\2\3/'  Input_file

【讨论】:

    【解决方案2】:

    为了完整性...

    posix shell

    while IFS= read -r line; do
        car=${line%%)*}
        caar=${car%%(*}
        cdar=${car##*(}
        cdr=${line#*)}
        printf '%s\n' "$caar,$cdar$cdr"
    done < file
    

    我认为你不能单独使用cut 来解决。

    【讨论】:

      【解决方案3】:

      任你选:

      $ sed 's/(\([^)]*\))/,\1/' file
      Col1,col2,col3,col4,col5
      a,23,12,test(1),test2
      b,30,15,test1(2),test3
      
      $ sed 's/(/,/; s/)//' file
      Col1,col2,col3,col4,col5
      a,23,12,test(1),test2
      b,30,15,test1(2),test3
      

      .

      $ awk '{sub(/\(/,","); sub(/\)/,"")} 1' file
      Col1,col2,col3,col4,col5
      a,23,12,test(1),test2
      b,30,15,test1(2),test3
      
      $ awk 'match($0,/\([^)]*\)/){$0= substr($0,1,RSTART-1) "," substr($0,RSTART+1,RLENGTH-2) substr($0,RSTART+RLENGTH) } 1' file
      Col1,col2,col3,col4,col5
      a,23,12,test(1),test2
      b,30,15,test1(2),test3
      
      $ awk 'BEGIN{FS=OFS=","} split($1,a,/[()]/) > 1{$1=a[1] "," a[2]} 1' file
      Col1,col2,col3,col4,col5
      a,23,12,test(1),test2
      b,30,15,test1(2),test3
      
      $ gawk '{$0=gensub(/\(([^)]*)\)/,",\\1",1)} 1' file
      Col1,col2,col3,col4,col5
      a,23,12,test(1),test2
      b,30,15,test1(2),test3
      
      $ gawk 'match($0,/([^(]*)\(([^)]*)\)(.*)/,a){$0=a[1] "," a[2] a[3]} 1' file
      Col1,col2,col3,col4,col5
      a,23,12,test(1),test2
      b,30,15,test1(2),test3
      

      最后两个需要 GNU awk 用于 gensub() 和第 3 个 arg 分别用于 match()。还有其他选择。

      【讨论】:

      • 如果您解释了每个解决方案,您可以大大改善您的答案。仅代码答案对 SO 社区没有那么重要。
      • @WiktorStribiżew 我完全不同意。 OP 将通过查找手册页来理解这些琐碎的脚本,而不是我为每个脚本编写解释来了解更多。教人钓鱼……
      猜你喜欢
      • 2021-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-25
      • 1970-01-01
      • 2011-05-03
      • 1970-01-01
      相关资源
      最近更新 更多