如何在 bash 中的任意数量的空格之后搜索和替换字符串?

Posted

技术标签:

【中文标题】如何在 bash 中的任意数量的空格之后搜索和替换字符串?【英文标题】:How do I search and replace a string after an arbitrary amount of white space in bash? 【发布时间】:2022-01-08 10:31:10 【问题描述】:

我正在使用 bash shell。我有一个仅包含该行的文本文件

name           "Test Program"

我想在名称后面的字符串周围添加花括号,使文件看起来像

name            “Test Program" 

我尝试了下面的表达式

perl -pi -e 's/name(\s+)"(.*)"/name$1 "$2" /g' /tmp/test.txt

但最终得到的文件只包含

name           

我对任意空白 (\s) 或替换是否有误解?

【问题讨论】:

sed 's/".*"/ & /' file? 我认为 应该是" 转义 perl 命令中的大括号:perl -pi -e 's/name(\s+)"(.*)"/name$1\ "$2" \/g' /tmp/test.txt @Dave:任意空格是什么意思?在 Perl 正则表达式中,\s 表示单个空格字符(空格、制表符或换行符)。 【参考方案1】:
perl -pi -e 's/name(\s+)"(.*)"/name$1 "$2" /g' /tmp/test.txt

这里,$1 "$2" 被解释为“%1 哈希的$2 键”。

$1 变量周围加上大括号以消除扩展的歧义:

perl -pi -e 's/name(\s+)"(.*)"/name$1 "$2" /g' /tmp/test.txt
# ..................................^.^

或转义左大括号

perl -pi -e 's/name(\s+)"(.*)"/name$1\ "$2" /g' /tmp/test.txt
# ...................................^

或者,使用\K 运算符

perl -pi e 's/name\s+\K(".*")/ $1 /' test.txt

【讨论】:

【参考方案2】:

假设只有一对双引号,并且不限于perl 解决方案...

一个想法使用sed

sed -E 's/("[^"]*")/ \1 /' test.txt

地点:

-E - 启用扩展正则表达式(和捕获组) ("[^"]*") - (捕获组)匹配 " + 0 个或多个 non-" 字符 + " \1 - 将匹配替换为 + 捕获组 +

这会生成:

name            "Test Program" 

一旦结果正确,您可以添加-i 标志以对源文件进行更改,例如:

$ cat test.txt
name           "Test Program"

$ sed -Ei 's/("[^"]*")/ \1 /' test.txt

$ cat test.txt
name            "Test Program" 

假设我们需要验证 name 字符串的匹配...

sed -E 's/([[:space:]]*name[[:space:]]+)("[^"]*")/\1 \2 /' test.txt

地点:

([[:space:]]*name[[:space:]]+) -(第一​​个捕获组)是 0 个或多个空格 + name + 1 个或多个空格 ("[^"]*") - (第二个捕获组)解释和以前一样 \1 \2 - 第一个捕获组 + + 第二个捕获组 +

示例数据文件:

$ cat test.txt
name           "Test Program"
  name         "Test Program"
boat           "Test Program"
names          "Test Program"

$ sed -E 's/([[:space:]]*name[[:space:]]+)("[^"]*")/\1 \2 /' test.txt
name            "Test Program" 
  name          "Test Program" 
boat           "Test Program"
names          "Test Program"

【讨论】:

谢谢!关于 'sed -E 's/([[:space:]]*name[[:space:]]+)("[^"]*")/\1 \2 /'test.txt',有什么方法可以修改它以使编辑到位?现在它正在将结果输出到屏幕上。最终我想将一堆文件传递给命令并让它们在每个文件上运行。 @Dave 是的,您可以对文件进行编辑...如前所述,添加 -i 标志(参见示例 - 上面 - sed -Ei ...【参考方案3】:

尝试使用 sed:

cat test.txt | sed 's/^name[ ]\+/name        /g' | sed 's/["][ ]*$/" /g'

【讨论】:

这会在屏幕上输出 'name "Test Program" ',但我想要 'name "Test Program" '。另外,有什么方法可以直接在文件中进行更改而不将它们输出到屏幕上?【参考方案4】:

你可以使用这个perl 命令:

perl -i -pe 's/(name\s+)("[^"]+")/$1  $2 /' file

cat file

name             "Test Program" 

或者这个sed

sed -i.bak -E 's/(name[[:blank:]]+)("[^"]+")/\1  \2 /' file

【讨论】:

以上是关于如何在 bash 中的任意数量的空格之后搜索和替换字符串?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 bash 脚本替换文件名中的空格

如何在bash中将空格替换为新行[重复]

Bash 递归替换名称上的许多空格

正则表达式 Python - 用单个空格替换换行符、制表符、空格的任意组合[重复]

替换空格

替换空格