Board logo

标题: [文本处理] 使用sed用正则替换文本时,什么情况下竖线【|】前要加^ [打印本页]

作者: kidzgy    时间: 2023-8-8 01:55     标题: 使用sed用正则替换文本时,什么情况下竖线【|】前要加^

本帖最后由 kidzgy 于 2023-8-8 01:57 编辑

【extensions.json】内容
  1. "rootURI":"jar:file:///D:/Firefox115/Profiles/extensions/uBlock0@raymondhill.net.xpi!/","location":"app-profile"
  2. "path":"D:\\Firefox115\\Profiles\\extensions\\s3google@translator.xpi","skinnable":false,
复制代码
【sed.bat】内容
  1. @ECHO OFF&(PUSHD "%~DP0")
  2. set "firefox=%~dp0"
  3. sed.exe -i -r "s#(jar:file:\/\/\/)[^^,]+(profiles\/extensions|browser\/features)\/#\1%firefox:\=/%\2#gi" "extensions.json"
  4. sed.exe -i -r "s#(\"path\":\")[^^,]+(profiles\\\\extensions^|browser\\\\features)#\1%firefox:\=\\\\%\2#gi" "extensions.json"
  5. exit
复制代码



有个问题不明白,sed第一个替换语句,竖线【|】前是不用加【^】的,加了反而没有效果,第二个语句却是要加【^】,删除了反而没有效果。这两者为什么一个要加,一个不用加,百思不得其解。
作者: Five66    时间: 2023-8-8 13:11

【^】是bat的转义吧,竖线【|】是bat的管道符
第一个正好2对英文双引号,被当成2个字符串,因此不需要对【|】用【^】进行转义
第二个中的
"s#(\"path\":\")[^^,]+(profiles\\\\extensions^|browser\\\\features)#\1%firefox:\=\\\\%\2#gi"
应该是被bat当成了
s#(\"path\":\")[^^,]+(profiles\\\\extensions^|browser\\\\features)#\1%firefox:\=\\\\\2#gi
如果不用【^】对【|】进行转义的话,【|】会被bat当成管道符

可以试试直接echo一下看看,对比一下第二个带【^】和不带【^】的输出
echo "s#(\"path\":\")[^^,]+(profiles\\\\extensions^|browser\\\\features)#\1%firefox:\=\\\\%\2#gi"
echo "s#(\"path\":\")[^^,]+(profiles\\\\extensions|browser\\\\features)#\1%firefox:\=\\\\%\2#gi"

大概是这样子吧
作者: kidzgy    时间: 2023-8-8 14:34

【^】是bat的转义吧,竖线【|】是bat的管道符
第一个正好2对英文双引号,被当成2个字符串,因此不需要对【 ...
Five66 发表于 2023-8-8 13:11



    原来如此,谢谢答疑解惑。

我发现,在【|】之前,双引号个数不能是偶数个,这里的数量包括【s#】前的双引号,如果是偶数个,【|】之前就要加上【^】。
作者: Five66    时间: 2023-8-8 15:06

回复 3# kidzgy


    呃,可是1楼的bat里的sed 不都是奇数个么?
作者: kidzgy    时间: 2023-8-8 16:07

本帖最后由 kidzgy 于 2023-8-8 16:08 编辑

回复 4# Five66

第一个sed是奇数,第二个sed是偶数。
    所以在|前有奇数个双引号时,|前不需要加^。
作者: buyiyang    时间: 2023-8-8 23:33

因为在没有开延迟变量扩展时,预处理不会处理双引号内的特殊符号。
作者: GNGW    时间: 2024-3-20 10:38

回复 2# Five66


    问题一: 两段是不是:"s#(jar:file:\/\/\/)[^^,]+(profiles\/extensions|browser\/features)\/#\1%firefox:\=/%\2#gi" "extensions.json" 这两段?

    问题二:第二个中的
               "s#(\"path\":\")[^^,]+(profiles\\\\extensions^|browser\\\\features)#\1%firefox:\=\\\\%\2#gi"
               应该是被bat当成了
               s#(\"path\":\")[^^,]+(profiles\\\\extensions^|browser\\\\features)#\1%firefox:\=\\\\\2#gi
         是解释器去掉引号了吗?为什么一对比,好像不光这样,第二句比第一句还少了个%,以及如果是这种说法,猜想,或者机制的话,那"s#(jar:file:\/\/\/)[^^,]+(profiles\/extensions|browser\/features)\/#\1%firefox:\=/%\2#gi" "extensions.json" 不也会被去掉双引号,而|符被当成管道符吗?
作者: Five66    时间: 2024-3-20 17:55

回复 7# GNGW


    那是参数 , 会按一定规则去掉引号 (保留引号内的内容), 然后传递到命令中
作者: WHY    时间: 2024-3-20 22:23

回复 7# GNGW


    可以这样理解:
一般来说,双引号一般会成对出现,被 "双引号对" 包裹的字符串,其中的特殊字符并不需要转义。
因为成对出现的双引号,本身就具有转义特殊字符的作用。比如 echo "a|b" 中的特殊字符不需要转义。
但暴露在 "双引号对" 之外的字符串,其中的特殊字符需要转义。

"s#(\"path\":\")[^^,]+(profiles\\\\extensions^|browser\\\\features)#\1%firefox:\=\\\\%\2#gi"

红色、蓝色分别是两组被双引号包裹的字符串,剩余的字符串都暴露在 "双引号对" 的外面,暴露在外边的特殊字符^和|都要转义。
作者: WHY    时间: 2024-3-20 22:26

顺便说下,顶楼脚本不知楼主从哪抄的,单从 sed 语法上讲,很多转义是多余的。
  1. sed -i -r "s#(jar:file:///)[^,]+(profiles/extensions|browser/features)/#\1%firefox:\=/%\2#gi" a.txt
复制代码
  1. sed -i -r "s#(\x22path\x22:\x22)[^,]+(profiles\\\\extensions|browser\\\\features)#\1%firefox:\=\\\\%\2#gi" a.txt
复制代码

作者: GNGW    时间: 2024-3-21 09:02

回复  GNGW


    可以这样理解:
一般来说,双引号一般会成对出现,被 "双引号对" 包裹的字符串,其中 ...
WHY 发表于 2024-3-20 22:23



    那这样说的话,最后一个双引号和谁配对?没有配对也没有转义,解释器不会报语法错误?
作者: GNGW    时间: 2024-3-21 09:10

回复 8# Five66


    "s#(\"path\":\")[^^,]+(profiles\\\\extensions^|browser\\\\features)#\1%firefox:\=\\\\%\2#gi"
               应该是被bat当成了
               s#(\"path\":\")[^^,]+(profiles\\\\extensions^|browser\\\\features)#\1%firefox:\=\\\\\2#gi

我是说在您的回复中同样的位置,第一行和第二行对比是不是少了个%这是您没打字没打上,还是说蓄意为之。如果是的话,这又是什么语法,为什么解释器要去掉%?还有根据您上一次的回答这个答案中,如果规则中去掉最外围的双引号后,在
s#(\"path\":\")[^^,]+(profiles\\\\extensions^|browser\\\\features)#\1%firefox:\=\\\\\2#gi 还是有一个双引号没被配对。
作者: Five66    时间: 2024-3-21 15:05

回复 12# GNGW


    啊 , 确实是少了%
至于还是有一个双引号没被配对 , 那是因为跟参数解析规则并在了一起 , 参数解析规则中的\"其实就表示"(即转义")
分开来的话就像9楼说的那样 , cmd会先将命令和参数部分分解出来 , 然后再将参数部分按一定规则进行解析 传进命令里
参数解析规则参考
http://www.bathome.net/thread-3451-1-20.html
作者: GNGW    时间: 2024-3-21 17:01

回复 13# Five66


    所以根据这个结论,为什么要有两个转义字符?它们的作用范围或者说使用场景是不是不同?如何分别和搭配使用?
作者: GNGW    时间: 2024-3-21 17:09

回复  Five66

第一个sed是奇数,第二个sed是偶数。
    所以在|前有奇数个双引号时,|前不需要加^。
kidzgy 发表于 2023-8-8 16:07



    这个原因是因为预处理机制,在没有开延迟变量扩展的时候,在双引号的时候视为转义,(希望不要误解到你,这是我了解到的,不保证一定准确性,但肯定是双符号是转义),比如%%可以视为转义,\\,^^,“”,还有很多,http://www.bathome.net/redirect. ... 8649&pid=279265 我把帖子贴在这里,注意,帖子里的有些内容机制我也没有搞懂,所以分析之后可以跟帖纠正,或者补充,
作者: Five66    时间: 2024-3-21 19:11

回复 14# GNGW


\是参数解析步骤时的转义符(仅限转义\和") , 不是参数解析的情况下 , \只是个普通字符 , 一般是外部命令才会进行这个步骤 , 内部命令大部分不会进行这个步骤
^是常规转义符 , 代码解析步骤时使用 , 这步骤绝对会进行的
为啥这样 , 建议问微软

因为在英文双引号内(某种意义上这也是一个转义符) , ^是个普通字符  , %%(仅限脚本文件中)跟""是为了在双引号内的^符号失去了转义作用情况下 , 对双引号内的%和"转义的 , 像是亡羊补牢的感觉???  
其他的就不知道了
作者: WHY    时间: 2024-3-21 21:09

回复 11# GNGW


    是谁告诉你双引号必须配对,不配对就一定不行的?
只要没有语法错误,能够通过预处理这一关,CMD 就认为是OK的,下一步该干啥干啥。

CMD 比你想像的要聪明得多,如果字符串结尾没有引号字符,它会认为结尾已经存在一个隐含的、且与之配对的引号字符,比如:
echo;a"b|c
与 echo;a"b|c" 一样,| 不需要转义。

如果字符串结尾有一个不配对的引号字符,与 echo;a"b|c 道理一样,只是把 b|c 去掉了。

一个建议:
想学批处理,先学会基本命令、基本语法,练好基本功;
只有掌握了基础,再来钻研这些个 "奇技淫巧",才不会感到吃力。
潘多拉的魔盒,需要有魔力的人才可能打开,CMD的预处理就是"魔盒",没有谁敢说已经彻底打开。




欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2