sed:替换两个相似模式之间的模式,即(替换"到'两个",")

时间:2017-03-24 04:13:07

标签: sed

我有一个csv文件,其字段由双引号(")和逗号(,)分隔,例如:

"123","4"5""6","789"

但是,数据中可能会有一些双引号("),即4"5""6,我需要转换为单引号('),即

我需要转换

"123","4"5""6","789"

"123","4'5''6","789"

我尝试过像

这样的事情
sed "s/\(\",\"\)\(\"\|[^\(","\)]\)*\(\",\"\)/\1'\3/"g 

但仅限(\"\|[^\(","\)]\)*

匹配"或不","

但我可能需要像

这样的东西

匹配"而不是","

另一种方法可以是执行顺序sed,即

  1. 首先找到并匹配4" 5"" 6

  2. 将结果传递给下一个语句并替换为4' 5' ' 6

  3. 但对于这两种方式,我都不知道该怎么做。

    虽然我可以先将所有"替换为',然后重新格式化我的csv,但它似乎代价高昂,即 sed -i -e "s/\"/'/g" -e "s/','/\",\"/g" -e "s/^'/\"/g" -e "s/'$/\"/g" myFile.csv

5 个答案:

答案 0 :(得分:1)

试试这个:

$ sed ':a;s/\("[^,"]*\)"\([^,].*\)/\1'\''\2/;ta' <<< '"1"23","4"5""6","78"9"'
"1'23","4'5''6","78'9"

打开双引号并跟随下一个结束"的字符(但不包括)将被捕获并替换为捕获的字符串和单引号。

如果替换成功,ta将循环到脚本的开头以进行进一步替换。

答案 1 :(得分:0)

  

首先找到并匹配4&#34; 5&#34;&#34; 6

     

将结果传递给下一个语句并替换为4&#39; 5&#39; &#39; 6

这可以在perl

中使用
$ echo '"123","4"5""6","789"' | perl -pe 's/"\K[^,]+(?=")/$&=~s|"|\x27|gr/ge'
"123","4'5''6","789"
  • "\K[^,]+(?=")匹配列内容,使用lookarounds
  • 省略外部双引号
  • $&=~s|"|\x27|gr用单引号替换列内容中的双引号
    • 使用的e修饰符允许使用Perl代码而不是替换字符串


sed的解决方法涉及凌乱的分支

$ echo '"123","4"5""6","789"' | sed -E ':a s/("[^,]+)"([^,]+")(,|$)/\1\x27\2\3/; ta'
"123","4'5''6","789"
  • :a标记标记
  • ("[^,]+)"([^,]+")(,|$)将列内容与至少一个内部双引号匹配
  • \1\x27\2\3用单引号
  • 替换内部双引号 只要有匹配
  • ta分支到a标签

答案 2 :(得分:0)

echo '"123","4"5""6","789"'|sed -r ':a;s/^([^,]+,"[^,]*)"([^"]*",)/\1\x27\2/;ta'

答案 3 :(得分:0)

您可以使用以下//After Open Upload window //Copy the file path in clipboard StringSelection ss=new StringSelection("File path"); Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, null); //Paste your copied path in modal window using mouse events Robot rb=new Robot(); rb.keyPress(KeyEvent.VK_CONTROL); rb.keyPress(KeyEvent.VK_V); rb.keyRelease(KeyEvent.VK_CONTROL); rb.keyRelease(KeyEvent.VK_V); rb.keyPress(KeyEvent.VK_ENTER); rb.keyRelease(KeyEvent.VK_ENTER); 方法:

awk

输出:

echo '"123","4"5""6","789"' | awk -F, '{OFS=","; $2="\""gensub(/\042/, "\047","g", substr($2, 2, length($2)-2))"\"";}1'

说明:

"123","4'5''6","789" -F,) - 将OFS=","视为字段分隔符

, - 双引号ASCII八进制代码

"\042" - 单引号ASCII八进制代码

"\047" - 从第二个字段中提取子字符串,除了尾随双引号,即substr($2, 2, length($2)-2)

4"5""6 - 用 target 字符串中的单引号替换所有双引号

答案 4 :(得分:0)

另一个awk提议:

echo '"123","4"5""6","789"' |awk '{sub(/4"5""/,"4\47"5"\47\47")}1'

"123","4'5''6","789"