在sed中使用正则表达式查找替换

时间:2013-06-06 17:18:26

标签: regex sed terminal

我正在尝试编写一个表达式来替换名为testRegex.csv

的文件
{"type":"MultiPolygon","coordinates":[[[-74.043886,40.690185 -74.040365,40.700704 -74.040288,40.700644 -74.03995,40.700891]]]}

用这个

{"type":"MultiPolygon","coordinates":[[[[-74.043886,40.690185], [-74.040365,40.700704], [-74.040288,40.700644], [-74.03995,40.700891]]]}

我尝试了以下

sed 's/(\W\d\d[.]\d*[,]\d\d[.]\d*)/[$1],/g' <testRegex.csv >testRegex2.csv
sed 's/(\W\d\d[\.]\d*[\,]\d\d[\.]\d*)/[$1]\,/g' <testRegex.csv >testRegex2.csv
sed 's/(\W\d\d\.\d*\,\d\d\.\d*)/[$1]\,/g' <testRegex.csv >testRegex2.csv

任何人都可以看到为什么这些不起作用?

2 个答案:

答案 0 :(得分:2)

尝试以下方法:

sed -E -e 's/([0-9-]+\.[0-9]*,[0-9-]+\.[0-9]*)/[\1],/g' -e 's/,]/]/'

请注意,在某些系统上,您可能需要将-E选项替换为-r,这是扩展正则表达式支持的选项。

答案 1 :(得分:0)

我试图解决比接受的答案稍微难一些的问题 - 并且开发了一个答案,它不会改变输出格式中的行。这很难,但可以做到(ERE支持比传统的sed BRE符号更简洁)。

BRE符号

sed '/\([^[]\[\[\[\)\(\(\[[-+]*[0-9][0-9]*\.[0-9]*,[-+]*[0-9][0-9]*\.[0-9]*\], \)*\)\([-+]*[0-9][0-9]*\.[0-9]*,[-+]*[0-9][0-9]*\.[0-9]*\)/ {
: redo
s//\1\2[\4],/
t redo
s/,]]]/]]]/
}' <<'EOF'

{"type":"MultiPolygon","coordinates":[[[-74.043886,40.690185 -74.040365,40.700704 -74.040288,40.700644 -74.03995,40.700891]]]}
with this

{"type":"MultiPolygon","coordinates":[[[[-84.043886,40.690185], [-64.040365,40.700704], [-74.040288,40.700644], [-74.03995,40.700891]]]}
EOF

ERE表示法

sed -E '/([^[]\[\[\[)((\[[-+]?[0-9]+\.[0-9]+,[-+]?[0-9]+\.[0-9]+\], )*)([-+]?[0-9]+\.[0-9]+,[-+]?[0-9]+\.[0-9]+)/ {
: redo
s//\1\2[\4],/
t redo
s/,]]]/]]]/
}' <<'EOF'

{"type":"MultiPolygon","coordinates":[[[-74.043886,40.690185 -74.040365,40.700704 -74.040288,40.700644 -74.03995,40.700891]]]}
with this

{"type":"MultiPolygon","coordinates":[[[[-84.043886,40.690185], [-64.040365,40.700704], [-74.040288,40.700644], [-74.03995,40.700891]]]}

EOF

示例输出

{"type":"MultiPolygon","coordinates":[[[[-74.043886,40.690185], [-74.040365,40.700704], [-74.040288,40.700644], [-74.03995,40.700891]]]]}
with this

{"type":"MultiPolygon","coordinates":[[[[-84.043886,40.690185], [-64.040365,40.700704], [-74.040288,40.700644], [-74.03995,40.700891]]]}

ERE的说明

/([^[]\[\[\[)((\[[-+]?[0-9]+\.[0-9]+,[-+]?[0-9]+\.[0-9]+\], )*)([-+]?[0-9]+\.[0-9]+,[-+]?[0-9]+\.[0-9]+)/

这可以分为3个子正则表达式:

  1. ([^[]\[\[\[) 这匹配前面不是方括号的三个方括号。它在替换中变为\1
  2. ((\[[-+]?[0-9]+\.[0-9]+,[-+]?[0-9]+\.[0-9]+\], )*) 这有两个捕获,但我真的对外部感兴趣。内部一个查找一个方括号,后跟一个可能有符号的数字(它坚持使用前面至少一个数字和小数点后一位数),一个逗号,另一个可能有符号的数字,一个紧密的方括号(反斜杠不是是绝对必要的,还有逗号和空格。这个内部捕获将是\3,并且可以重复零次或多次。外部捕获捕获\3的所有重复,称为\2。如果没有使用外部捕获,那么内部捕获不会捕获“方括号中的数字对”的最后一次重复,而使用两次捕获,您将获得所有重复。
  3. ([-+]?[0-9]+\.[0-9]+,[-+]?[0-9]+\.[0-9]+) 这会捕获一对以逗号分隔的可能已签名的数字。
  4. 替换脚本使用条件sed循环:

    {
    : redo
    s//\1\2[\4],/
    t redo
    s/,]]]/]]]/
    }
    

    : redo设置标签。 s//\1\2[\4],/用括号括起来的相同信息替换第一个未加括号的“逗号分隔的一对可能签名的数字”。添加g后缀不起作用;该模式必须解决以前匹配的文本。因此,如果已经替换,则有t redo有条件地跳回标签redo。最后的s///删除了方括号中最后一对新数字后添加的逗号。

    请注意,BRE正则表达式不会坚持小数点后的数字;它可以做得更长,以便它(在四个小数点的每一个之后添加额外的[0-9])。