将正则表达式应用于标准输入

将正则表达式应用于标准输入

在编程中我们经常会看到使用常用表达

最常见的形式之一是:

newText = text.replace( /regex/, 'replacementString' )

如果标准输入text并且标准输出newText,与上面的代码等效的 bash 是什么?

答案1

对于简单的用途,你可以这样做:

newText=${text/SEARCH/replacement}

正如所描述的这里,但对于更复杂的表达式 sed 是像 alex 之前描述的那样。

答案2

最直接的答案是seds命令。您需要将正则表达式语法转换为基本正则表达式,并且替换将连续应用于每一行。您可以使用\1through\9来引用原始字符串中带括号的组。添加g修饰符以替换所有出现的情况;否则仅替换第一个出现的位置。

sed -e 's/basic regexp/replacement string/g'

更灵活的实用程序是awk。默认情况下,它也逐行处理其输入,但您可以使用以下命令更改记录分隔符-vRS=…(标准 awk 需要单个字符,或者空值表示两个或多个换行符;Gawk(GNU 版本)接受正则表达式)。该sub函数执行单个替换,并gsub替换所有出现的情况。替换字符串按字面解释,除了\&;如果要引用括号内的组,可以使用matchsubtring函数。

awk '{gsub(/regexp/, "replacement string")}'

Bash 内置了对正则表达式匹配的支持:[[ text =~ regexp ]].您可以使用数组中存储的匹配子字符串构造替换文本BASH_REMATCH。使用readcat获取输入并printf发出输出。以下伪代码执行多次替换(警告,未经测试;代码应该像往常一样从左到右执行多次替换,我希望我做对了)。

# The end marker must not have a prefix that is a suffix of a match of the regexp,
# and must not start or end with a newline
end_marker='EOF'
text=$(cat; echo "$end_marker")
while [[ $text =~ regexp(.*)$ ]]; then
    printf %s%s "${text%"$BASH_REMATCH[0]"}" "replacement string"
    text=$BASH_REMATCH[$#BASH_REMATCH]
  fi
done
printf %s "${text%"$end_marker"}"

(解释几句:结束标记是为了避免尾随换行符被命令替换删除。${text%"$BASH_REMATCH[0]"}提取匹配之前的文本部分。请注意,我们不能^(.*)在正则表达式的开头使用,否则我们' d 获取最后一个匹配项而不是第一个匹配项。匹配后,我们迭代后缀,最后打印不匹配的剩余部分,减去结束标记。)

如果您对通配符匹配和有限的替换文本功能感到满意,bash 还具有${variable/pattern/replacement}.将第一个斜杠加倍以替换所有出现的斜杠。如果extglob设置了该选项,模式确实具有正则表达式的功能(但具有不寻常的语法) 。

答案3

  • man sed
  • sed s/regex/replacementString/g

答案4

您可以使用sed和之类的工具awk,但在我看来,它们非常过时,仅对狭义定义的任务有用。

更好的选择是将 STDIN 重定向到 Perl 单行代码或脚本。 perl 的正则表达式支持非常好,以至于大多数其他语言现在都支持与它们的某些兼容性。甚至还有a2p工具s2p可以将 sed 和 awk 直接转换为 Perl。使用 perl 允许您使用整个 CPAN 来帮助您解决问题。

如果您不喜欢 perl,您可以使用 python 来实现类似的功能。

相关内容