在文本文件中搜索下划线前面带有标点符号--- [.?!;:]_
---我希望撤消其订单。
例如,给定行
On this _line,_ I show an example. !_
我希望将其更改为:
On this _line_, I show an example. _!
我可以找到所有案例,比如Silver Searcher或ripgrep:
rg '[.?!;:]_' myfile.txt
但我不确定如何将这两个字符交换并就地写入或写入新文件。
我可以为每个标点符号实例使用sed
,例如:
sed -ie 's/,_/_,/g' myfile.txt
然后
sed -ie 's/\._/_\./g' myfile.txt
...然后
但用一个命令执行此操作会很好。
我可以参考找到的实例并在ripgrep的-r ARG
选项中使用它吗?
或者我咆哮错误的树并明智地使用另一个工具?
答案 0 :(得分:2)
sed
支持在替换参数中s
调用的regex参数中定义的捕获组的反向引用(使用bash
here-string语法({{ 1}})为了简洁起见:
<<<
$ sed -E 's/([.?!;:])_/_\1/g' <<<'On this _line,_ I show an example. !_'
On this _line,_ I show an example. _!
是指正则表达式中的第一个捕获组(\1
)。
请注意,(...)
用于启用对使用现代语法的扩展正则表达式的支持 - GNU -E
和BSD / macOS sed
都支持此选项
通常,您不需要sed
的{{1}}选项,除非您在多个部分中传递sed
脚本,在这种情况下每个部分必须是-e
- 前缀。
对于 就地更新输入文件:
sed
可能不做(完全)你想要的东西:当它确实更新输入文件时(通过用更新内容替换新文件),它会创建一个< em>带有后缀-e
的备份文件,因为-ie
被解释为选项e
的选项参数。
如果意图不来创建备份文件,则语法 - 遗憾的是 - 根据您正在使用的e
实现而有所不同:
GNU -i
:sed
sed
必须不后面跟着任何其他选项/字符。 BSD / macOS sed -i ...
:-i
sed
必须后跟sed -i '' ...
作为下一个单独的参数。答案 1 :(得分:1)
这是一种只用一行就能做到的方法:
sed 's/\([^\w\s]\)\(_\)/\2\1/g' test.txt
基本上,你正在寻找两个角色,然后交换它们。
s / - 这开始替换
\( \)
- 这会绕过括号。要做到这一点,即使它很难看。
\s
一个空格字符
[ ]
设置一个字符类
^
否定字符类中的第一个位置
[^\w\s]
所有不是字母或空格的字符(又名标点符号)
然后我们进入下一场比赛,一个下划线。我们将此作为第二项检查
\(_\)
- 首先,找到标点符号并将其标记为匹配编号1,然后在其旁边找到一个下划线,并将其标记为匹配编号2.
/\2\1/
- 现在,交换匹配1和2
/g
- 全球范围内这样做。
结束。现在,您可以将其输出到另一个文件,或使用其他sed
修饰符(-i
开关)来内联更改文件。