如何在冒号之前使用正则表达式进行替换?

3

这是我的原始字符串:

NetworkManager/system connections/Wired 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1

我只想在冒号前的所有空格添加反斜杠

因此,这就是我最终想要的:

NetworkManager/system\ connections/Wired\ 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1

我需要用bash执行这个操作,所以sed、awk、grep都可以。

我尝试了以下的sed命令,但是它们都无法正常工作。

echo NetworkManager/system connections/Wired 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1 | sed 's/ .*\(:.*$\)/\\ .*\1/g'
echo NetworkManager/system connections/Wired 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1 | sed 's/\( \).*\(:.*$\)/\\ \1.*\2/g'
echo NetworkManager/system connections/Wired 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1 | sed 's/ .*\(:.*$\)/\\ \1/g'
echo NetworkManager/system connections/Wired 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1 | sed 's/\( \).*\(:.*$\)/\\ \1\2/g'

感谢您回答我的问题。我还是StackOverflow的新手,不知道如何在评论中控制格式。因此,我只编辑了我的原始问题。
我的真实故事是:
当我使用grep或者cscope搜索/etc文件夹下的关键词,例如“address1”,结果看起来会像这样:
./NetworkManager/system connections/Wired 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1

如果我使用vim编辑器打开光标下的文件,举个例子假设我的vim光标现在在单词“NetworkManager”上, 那么vim会理解为

"./NetworkManager/system"

这就是我想在空格前加"\ "的原因,这样搜索结果会更符合vim编辑器的要求:)

我试过修改cscope的源代码,但是很难完全实现。所以只能进行后处理替换:(


2
如果您可以使用支持\K(重置匹配的开始并且丢弃所有先前匹配的字符)和\G(将位置设置为上一个匹配的结尾或在第一个匹配之前的字符串的开头),例如Perl这样的平台,您可以使用以下正则表达式进行替换:^[^:]*?\K |\G[^:]*?\K 。(每个\K后面都有一个空格。)演示。将光标悬停在链接中正则表达式的每个元素上以获取其功能的解释。 - Cary Swoveland
2
这听起来很像一个XY问题,你试图通过转义空格而不是引用字符串来解决输入中的空格问题,特别是考虑到你在问题中使用的echo缺少引号。你对这些字符串做了什么让你认为需要在空格前添加反斜杠? - Ed Morton
@EdMorton 谢谢您的提问。 我的真实经历是: 当我在/etc文件夹下使用grep或cscope搜索关键字“address1”时, 结果会像这样:./NetworkManager/system connections/Wired 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1如果我使用vim打开光标下的文件,假设我的vim光标现在位于单词“NetworkManager”, 那么vim将把它理解为"./NetworkManager/system"这就是为什么我想在空格前面添加“\”,这样搜索结果就更适合vim了 :) - huangyingw
作为一个几乎每天都使用 grepcscope 工具约 30 年的人,我从未遇到过这个问题。我一直使用的是 vi 而不是 vim,虽然我从未尝试在 vi 中打开文件。根据我们在这里看到的问题,似乎很多人使用 vim 来处理更适合使用 shell 的事情! - Ed Morton
5个回答

5
如果您只希望在字符串中存在时进行替换,您可以检查是否至少有2列,并将(输出)字段分隔符设置为冒号。
数据:
cat file                                                                                                                                       michaelvandam@Michaels-MacBook-Pro
NetworkManager/system connections/Wired 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1
NetworkManager/system connections/Wired 1.nmconnection 14 address1=10.1.10.71/24,10.1.10.1%

awk中的示例:

awk 'BEGIN {FS=OFS=":"}{if(NF>1)gsub(" ","\\ ",$1)}1' file

输出

NetworkManager/system\ connections/Wired\ 1.nmconnection:14 address1=10.1.10.71/24,10.1.10.1
NetworkManager/system connections/Wired 1.nmconnection 14 address1=10.1.10.71/24,10.1.10.1

4
这可以通过 awk 程序简单完成,针对您展示的样本,请尝试以下操作。
awk 'BEGIN{FS=OFS=":"} {gsub(/ /,"\\\\&",$1)} 1' Input_file

说明:简单来说,这个程序将字段分隔符和输出字段分隔符设置为冒号(:)。然后在主程序中使用awk的gsub(全局替换)函数,在仅第一个字段中将空格替换为\ (根据OP的备注,应在:之前进行),然后打印该行。


3

1
这可能对您有用(GNU sed):
 sed -E ':a;s/^([^: ]*) /\1\n/;ta;s/\n/\\ /g' file

将冒号前的空格替换为换行符,然后将换行符替换为 \

使用保留空间的替代方法:

 sed -E 's/:/\n:/;h;s/ /\\ /g;G;s/\n.*\n//' file

将文本在第一个:处分割。

修改前面的部分,删除中间的部分并添加未经过处理的后面的部分。


第一个在macOS上不起作用,第二个可以正常工作。 - huangyingw
@huangyingw,您是在说第一个GNU sed解决方案在macOS中无法工作吗? - potong
正确的,在macOS中第一个不起作用。 - huangyingw

0

我的答案很丑,我认为RavinderSingh13的答案是最好的,但我已经花时间写了我的答案并且它也能正常工作(虽然是一行命令,但是我写了详细的步骤):

我受到了HatLess的答案的启发:

首先使用cut获取:之前的文本(我将字符串放入文件中以便于阅读,但这也适用于echo):

cut -d':' -f1 infile

然后使用sed替换空格:

cut -d':' -f1 infile | sed 's/\([a-z]\) /\1\\ /g'

接下来使用echo命令输出结果,但不要换行:

echo -n "$(cut -d':' -f1 infile | sed -e 's/\([a-z]\) /\1\\ /g')"

添加缺失的:以及其后的内容:

echo -n "$(cut -d':' -f1 infile | sed -e 's/\([a-z]\) /\1\\ /g')" | cat - <(echo -n :) | cat - <(cut -d':' -f2 infile)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接