在bash中使用正则表达式进行搜索和替换

19 浏览
0 Comments

在bash中使用正则表达式进行搜索和替换

我见过这个例子:\n

hello=ho02123ware38384you443d34o3434ingtod38384day
echo ${hello//[0-9]/}

\n其遵循以下语法:${variable//pattern/replacement}\n不幸的是,pattern字段似乎不支持完整的正则表达式语法(例如,如果我使用.\\s,它会尝试匹配字面字符)。\n如何使用完整的正则表达式语法搜索/替换字符串?

0
0 Comments

搜索和替换在bash中使用正则表达式的问题是由于以下原因而出现的:在bash中使用的正则表达式不支持PCRE(Perl-compatible regular expressions)扩展,这些扩展在其他编程语言中是支持的,如php、ruby和python。因此,使用这些扩展的正则表达式无法在bash中正常工作。

解决这个问题的方法是使用bash中支持的正则表达式语法进行搜索和替换。在上面的例子中,使用了bash中的字符串替换语法${MYVAR//[a-zA-Z]/X}${MYVAR//[0-9]/N}来替换字母和数字。另外,也可以使用字符类括号表达式${MYVAR//[[:alpha:]]/X}${MYVAR//[[:digit:]]/N}来替换字母和数字。

然而,如果想要使用PCRE扩展的正则表达式,可以使用其他工具如sed或perl来实现。在上面的例子中,使用了perl命令echo $hello | perl -pe 's/\d//g'来替换数字。需要注意的是,使用sed命令echo $hello | sed 's/\d//g'来替换数字时,并不起作用。这是因为bash中的正则表达式和PCRE的语法不兼容。

总结一下,搜索和替换在bash中使用正则表达式的问题是由于bash不支持PCRE扩展的正则表达式语法而导致的。解决这个问题的方法是使用bash中支持的正则表达式语法进行搜索和替换,或者使用其他工具如sed或perl来实现PCRE扩展的正则表达式。

0
0 Comments

在bash中使用正则表达式进行搜索和替换的问题是因为在纯bash中可以实现这一功能。可以使用`=~`运算符来匹配正则表达式,并在循环中重新赋值。然而,这种方法有点笨拙,因为需要在循环中重新赋值。另一种解决方法是调用sed或perl命令。如果每次调用这些命令处理的是多行输入而不是在循环中调用,那么调用它们是明智的。在zsh中,可以使用`$match`代替`$BASH_REMATCH`来获取匹配结果。然而,使用zsh时,这个决定似乎有些不合理,因为它使用应用程序变量命名空间而不是系统命名空间。此外,在某些情况下,如果要匹配换行符,可以使用`$'\n'`。然而,某些情况下不需要使用括号或大括号表达式,可以直接使用`[[ $some_var =~ $'\n' ]]`进行匹配。另外,可以使用`shellcheck`工具来检查bash脚本的语法错误。对于可能导致无限循环的空匹配,可以通过改变正则表达式来避免这个问题,或者在循环的条件中添加`[[ ${BASH_REMATCH[2]} ]]`来检查匹配结果的长度。这个问题的解决方法有多种,具体取决于具体的需求和情况。

0
0 Comments

在bash中使用正则表达式进行搜索和替换的问题是由于需要对字符串进行替换操作而产生的。解决方法是使用sed或其他类似的工具来实现替换操作。下面是一些解决方法的示例:

使用sed命令:

MYVAR=ho02123ware38384you443d34o3434ingtod38384day
echo "$MYVAR" | sed -e 's/[a-zA-Z]/X/g' -e 's/[0-9]/N/g'
# 输出:XXNNNNNXXXXNNNNNXXXNNNXNNXNNNNXXXXXXNNNNNXXX

注意,后续的`-e`选项按顺序处理。此外,表达式中的`g`标志将匹配输入中的所有出现。

你也可以选择你喜欢的工具来实现替换操作,比如perl或awk:

echo "$MYVAR" | perl -pe 's/[a-zA-Z]/X/g and s/[0-9]/N/g'

这种方法可以实现更灵活的匹配。例如,在上面的示例中,只有在第一个表达式匹配成功时才会使用数字替换(由于惰性`and`评估)。当然,你可以利用Perl的完整语言支持来实现更复杂的操作。

这种方法似乎只能进行单个替换。有没有办法像我发布的代码那样替换所有匹配的模式呢?

我更新了我的答案,演示了多个替换以及全局模式匹配。如果有帮助,请告诉我。

非常感谢!出于好奇,你为什么从一行版本(在你最初的答案中)改成了两行版本?

你为什么使用全大写的`MYVAR`?最佳实践是将全大写保留给环境变量和shell内置命令,以避免命名空间冲突。

使用sed或其他外部工具会因为进程初始化时间而导致性能损失。我特别搜索了所有基于bash的解决方案,因为我发现使用bash替换比每个循环项调用sed要快3倍以上。

诚然,这是一种常见的做法,但这并不意味着它是明智的。是的,无论如何,bash都很慢 -- 但是写得好的避免子shell的bash比调用外部工具执行每个小任务的bash快几个数量级。此外,良好编写的shell脚本将受益于更快的解释器(如性能与awk相当的ksh93),而对于编写不良的脚本则无济于事。

为了说明调用外部工具的性能损失,以下是我在一个脚本中删除外部工具调用之前和之后使用`time`命令的输出结果。之前: `real 1m1.209s / user 0m45.342s / sys 0m13.142s` 之后: `real 0m3.433s / user 0m2.519s / sys 0m0.211s` 快了94%!!

我建议使用perl而不是sed,因为在Linux版本的sed和在MacOS上使用的BSD版本之间存在可移植性问题。

我认为可以安全地假设,如果某人使用Mac并且关心bash脚本的性能,他们可能已经运行了`brew install coreutils`。

如果你想将输出保存回变量中,可以使用以下命令:

MYVAR=$(echo "$MYVAR" | sed -e 's/[a-zA-Z]/X/g' -e 's/[0-9]/N/g')

在对变量赋值时,应该使用`-n`选项来避免echo附加换行符,例如:

MYVAR=$(echo -n "$MYVAR" | sed -e 's/[a-zA-Z]/X/g' -e 's/[0-9]/N/g')

0