sed 正则表达式,数字格式:如何转义 bash

sed regexp, number reformatting: how to escape for bash

我有一个工作(在 macOS 应用程序模式中)RegExp 重新格式化 GeoJSON MultiPolygon 坐标,但不知道如何为 sed.

转义它

我正在处理的文件超过 90 Mb,因此 bash 终端看起来是理想的地方,sed 是完成这项工作的完美工具。

搜索文本示例:

[[[379017.735,6940036.7955],[379009.8431,6940042.5761],[379000.4869,6940048.9545],[378991.5455,6940057.8128],[378984.0665,6940066.0744],[378974.7072,6940076.2152],[378962.8639,6940090.5283],[378954.5822,6940101.4028],[378947.9369,6940111.3128],[378941.4564,6940119.5094],[378936.2565,6940128.1229],[378927.6089,6940141.4764],[378919.6611,6940154.0312],[378917.21,6940158.7053],[378913.7614,6940163.4443],[378913.6515,6940163.5893],[378911.4453,6940166.3531],

期望的结果:

[[[37.9017735,69.400367955],[37.90098431,69.400425761],[37.90004869,69.400489545],[37.89915455,69.400578128],[37.89840665,69.400660744],[37.89747072,69.400762152],[37.89628639,69.400905283],[37.89545822,69.401014028],[37.89479369,69.401113128],[37.89414564,69.401195094],[37.89362565,69.401281229],[37.89276089,69.401414764],[37.89196611,69.401540312],[37.891721,69.401587053],[37.89137614,69.401634443],[37.89136515,69.401635893],[37.89114453,69.401663531],

我当前的正则表达式:

((?:\[)[0-9]{2})([0-9]+)(\.)([0-9]+)(,)([0-9]{2})([0-9]+)(\.)([0-9]+(?:\]))

并重新格式化:

\.,.

命令应该是这样的:

sed -i -e 's/ The RegExp escaped /\.,./g' large_file.geojson

但是应该在 RegExp 中转义什么才能使其工作? 我的尝试总是抱怨不平衡。

如果这个问题已经在别处得到解答,我很抱歉,但即使经过广泛搜索我也找不到。


编辑:2017-01-07:我没有明确表示该文件包含 GPS 点以外的属性。从 GeoJSON Feature 属性中选取的其他示例值之一是 "35.642.1.001_001",应保持不变。由于这个原因,我原来的正则表达式中的大括号检查就在那里。

正则表达式在 sed 中不合法;因为它使用 Perl 语法,我的建议是改用 perl。正则表达式完全按原样工作,甚至命令行也几乎相同;您只需要添加 -p 选项即可使 perl 在过滤模式下运行(sed 默认情况下)。我还建议向 -i 选项添加一个参数后缀(无论是使用 sed 还是 perl),以便在出现严重错误时备份原始文件。至于引用,你需要做的就是将替换命令放在单引号中:

perl -p -i.bak -e \
's/((?:\[)[0-9]{2})([0-9]+)(\.)([0-9]+)(,)([0-9]{2})([0-9]+)(\.)([0-9]+(?:\]))/\.,./g' \
large_file.geojson

如果您的数据与您显示的一样,则无需担心括号。您可以使用启用了 -E 的 POSIX ERE(或在某些其他发行版中为 -r),如下所示:

sed -i -E 's/([0-9]{2})([0-9]*)\.([0-9]+)/./g' large_file.geojson

或 POSIX BRE:

sed -i 's/\([0-9]\{2\}\)\([0-9]*\)\.\([0-9]\+\)/./g' large_file.geojson

看到 online demo

您可能会看到 how this regex works here(只是演示,不是证明)。

请注意,在 POSIX BRE 中,您需要在限制/范围量词中转义 {},在分组结构中转义 (),和 + 量词,否则它们表示文字符号。在 POSIX ERE 中,您不需要对特殊字符进行转义以使其变得特殊,这种 POSIX 风格更接近于现代正则表达式。

此外,您需要在替换模式中使用 \n 符号,而不是 $n

一个简单的 sed 就可以做到:

$ echo "$var"
[[[379017.735,6940036.7955],[379009.8431,6940042.5761],[379000.4869,6940048.9545],[378991.5455,6940057.8128],[378984.0665,6940066.0744],[378974.7072,6940076.2152],[378962.8639,6940090.5283],[378954.5822,6940101.4028],[378947.9369,6940111.3128],[378941.4564,6940119.5094],[378936.2565,6940128.1229],[378927.6089,6940141.4764],[378919.6611,6940154.0312],[378917.21,6940158.7053],[378913.7614,6940163.4443],[378913.6515,6940163.5893],[378911.4453,6940166.3531],

$ echo "$var" | sed  's/\([0-9]\{3\}\)\././g'
[[[379.017735,6940.0367955],[379.0098431,6940.0425761],[379.0004869,6940.0489545],[378.9915455,6940.0578128],[378.9840665,6940.0660744],[378.9747072,6940.0762152],[378.9628639,6940.0905283],[378.9545822,6940.1014028],[378.9479369,6940.1113128],[378.9414564,6940.1195094],[378.9362565,6940.1281229],[378.9276089,6940.1414764],[378.9196611,6940.1540312],[378.91721,6940.1587053],[378.9137614,6940.1634443],[378.9136515,6940.1635893],[378.9114453,6940.1663531],