【问题标题】:Unix - Remove internal double quote with terminator commaUnix - 使用终止符逗号删除内部双引号
【发布时间】:2019-08-11 00:00:00
【问题描述】:

输入文件:

"1","2col",""3col " "
"2","2col"," "3c,ol     " "
"3","2col"," 3co,l"     
"4","2col","3co,l"
"5","2col",""3co,l      ""              "
"6","2col",""3c,ol ""3c,ol"""

输出文件:

"1","2col","3col    "
"2","2col"," 3c,ol       "
"3","2col"," 3co,l"     
"4","2col","3co,l"
"5","2col","3co,l                       "
"6","2col","3c,ol 3c,ol"

请帮助我使用 Unix 命令获得上述输出。请注意输出中的第 3 列已修改,所有内部双引号均已删除。

逗号是结束符。当双引号之间存在逗号时,它不被视为终止符。请参见第 6 行,在第 2 个逗号之后,逗号作为文本出现在双引号之间,这很好。

到目前为止我所做的尝试:

sed 's/""|/|/g'
sed -e "s/\"\"//g"
perl -pe 's/(?<!^)(?<!\,)"(?!\,)(?!$)/""/g'

【问题讨论】:

  • 嗨艾伦,sed 's/""|/|/g' 和 sed -e "s/\"\"//g" 和 perl -pe 's/(?
  • perlText::CSV 模块可能会成功。
  • 为什么在输入的第一行测试示例中你有 2 个尾随空格:"1","2col",""3col[ ]"[ ]",而在输出中你有 4(四个)尾随空格:"1","2col","3col[ ][ ][ ][ ]"?请调整示例,使其准确符合您的要求
  • 双引号在记录 5 中不平衡...你能澄清一下吗
  • @Allan 几天前我已经对以下答案投了赞成票。

标签: shell perl unix ksh


【解决方案1】:

假设(例如,第一列和第二列是“干净的”,它们不包含 ,

输入:

"1","2col",""3col " "
"2","2col"," "3c,ol     " "
"3","2col"," 3co,l"     
"4","2col","3co,l"
"5","2col",""3co,l      ""              "
"6","2col",""3c,ol ""3c,ol"""

命令:

tr -d '"' < input | awk -F',' -v OFS=',' '{$1="\""$1"\"";$2="\""$2"\"";printf $1 OFS $2 OFS "\"";for(u=3;u<=NF;u++){if(u!=NF)printf $u OFS;else printf $u};printf "\"" RS}'

输出:

"1","2col","3col  "
"2","2col"," 3c,ol      "
"3","2col"," 3co,l     "
"4","2col","3co,l"
"5","2col","3co,l                    "
"6","2col","3c,ol 3c,ol"

说明:

  • tr -d '"' &lt; input 将删除所有 "
  • | awk 将输出通过管道传输到 awk
  • -F',' -v OFS=',' 输入/输出字段分隔符定义为逗号
  • 使用$1="\""$1"\"";$2="\""$2"\""; 将前两列用" 包围,然后打印printf $1 OFS $2 OFS "\"";
  • for(u=3;u&lt;=NF;u++){if(u!=NF)printf $u OFS;else printf $u};printf "\"" RS} 对于该列的其余部分,您只需将它们重新附加在一起,然后在行尾添加最后一个 "

为了便于阅读:

'{
  $1="\""$1"\""
  $2="\""$2"\""
  printf $1 OFS $2 OFS "\""
  for(u=3;u<=NF;u++)
  {
    if(u!=NF)printf $u OFS
    else printf $u
  }
  printf "\"" RS
}'

【讨论】:

  • 前两个字段中的逗号将失败:"1","2,col","3col"
  • @WalterA:我已经编辑并添加了免责声明。在 OP 帖子中,col1 和 2 看起来不错,所以这就是为什么我根据这个假设构建我的解决方案。
【解决方案2】:

使用引号查找前两个字段并连接其他字段。

awk -F '"' '
   BEGIN {q="\""}
   {printf "%s", q$2q$3q$4q$5q; for (i=6;i<=NF;i++) printf "%s", $i; print q}
   ' inputfile

编辑:另一种选择

paste -d, <( cut -d"," -f1,2 < inputfile) \
          <( cut -d"," -f3-  < inputfile | sed 's/"//g;s/.*/"&"/')

编辑:另一种选择

sed 's/old/new/g:将替换应用于正则表达式的所有匹配项 seds/old/new/number`: 只替换正则表达式的第一个匹配项。 在 GNU sed 中混合 g 和 number 修饰符时,第一个匹配项将被忽略,然后匹配并替换所有匹配项。
在这种情况下:

sed -r 's/"//g6;s/$/"/' inputfile

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-24
    • 2016-03-18
    • 1970-01-01
    • 2018-07-27
    • 2023-03-03
    • 2020-01-19
    • 2020-08-03
    • 2019-08-11
    相关资源
    最近更新 更多