bash 支持字边界正则表达式吗?

2024-05-16

我试图在再次添加该单词之前匹配列表中是否存在该单词(以避免重复)。我正在使用 bash 4.2.24 并尝试以下操作:

[[  $foo =~ \bmyword\b ]]

also

[[  $foo =~ \<myword\> ]]

然而,这两种方法似乎都不起作用。它们在 bash 文档示例中提到:http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_04_01.html http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_04_01.html.

我认为我做错了什么,但我不确定是什么。


tl;dr

  • 为了安全起见,不要使用正则表达式literal with =~.
    相反,使用:

    • either: an 辅助变量 - see @Eduardo Ivancec 的回答 https://stackoverflow.com/a/9793094/45375.
    • or: 输出字符串文字的命令替换 - see @ruakh 对 @Eduardo Ivancec 的回答的评论 https://stackoverflow.com/q/9792702/45375#comment-12473988
    • 请注意,两者必须使用unquoted as the =~ RHS.
  • Whether \b and \< / \> are 完全支持取决于主机平台,不是 Bash:

    • 他们确实致力于Linux,
    • but NOT on BSD-based platforms such as macOS; there, use [[:<:]] and [[:>:]] instead, which, in the context of an unquoted regex literal, must be escaped as [[:\<:]] and [[:\>:]]; the following works as expected, but only on BSD/macOS:
      • [[ ' myword ' =~ [[:\<:]]myword[[:\>:]] ]] && echo YES # OK
  • The 问题就不会出现- 在任何平台上 -如果您将正则表达式限制为中的构造POSIX ERE(扩展正则表达式)规范 https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_04.

    • 不幸的是,POSIX ERE 确实not支持字边界断言,尽管您可以emulate他们 - 请参阅最后一节。

    • 与 macOS 上一样,no \支持前缀结构,因此可以使用方便的字符类快捷方式,例如\s and \w也不可用。

    • 然而,好的一面是,这样符合 ERE 的正则表达式那么是portable(例如,可在 Linux 和 macOS 上运行)

=~是罕见的情况(唯一的情况?)built-inBash 功能的行为是依赖于平台:它使用其运行平台的正则表达式库,从而导致不同平台上的不同正则表达式风格.

因此,它是通常并不简单,需要额外小心编写portable使用的代码=~操作员. 坚持使用 POSIX ERE 是唯一可靠的方法,这意味着您必须解决它们的局限性 - 请参阅底部部分。

如果您想了解更多信息,请继续阅读。


在 Bash v3.2+ 上(除非compat31 shopt选项已设置),RHS(右侧操作数)=~运算符必须是unquoted为了被认可为regex (如果你引用正确的操作数,=~执行常规字符串比较反而)。

More accurately, at least the special regex characters and sequences must be unquoted, so it's OK and useful to quote those substrings that should be taken literally; e.g., [[ '*' =~ ^'*' ]] matches, because ^ is unquoted and thus correctly recognized as the start-of-string anchor, whereas *, which is normally a special regex char, matches literally due to the quoting.

然而,似乎有一个设计限制在(至少)bash 3.x that 阻止使用\-前缀正则表达式构造(例如,\<, \>, \b, \s, \w, ...) 在一个literal =~ RHS;限制affects Linux,而 BSD/macOS 版本是not受到影响,因为根本不支持任何\-前缀正则表达式构造:

# Linux only:
# PROBLEM (see details further below): 
#   Seen by the regex engine as: <word>
#   The shell eats the '\' before the regex engine sees them.
[[ ' word ' =~ \<word\> ]] && echo MATCHES # !! DOES NOT MATCH
#   Causes syntax error, because the shell considers the < unquoted.
#   If you used \\bword\\b, the regex engine would see that as-is.
[[ ' word ' =~ \\<word\\> ]] && echo MATCHES # !! BREAKS
#   Using the usual quoting rules doesn't work either:
#   Seen by the regex engine as: \\<word\\> instead of \<word\>
[[ ' word ' =~ \\\<word\\\> ]] && echo MATCHES # !! DOES NOT MATCH

# WORKAROUNDS
  # Aux. viarable.  
re='\<word\>'; [[ ' word ' =~ $re ]] && echo MATCHES # OK
  # Command substitution
[[ ' word ' =~ $(printf %s '\<word\>') ]] && echo MATCHES # OK

  # Change option compat31, which then allows use of '...' as the RHS
  # CAVEAT: Stays in effect until you reset it, may have other side effects.
  #         Using (...) around  the command confines the effect to a subshell.
(shopt -s compat31; [[ ' word ' =~ '\<word\>' ]] && echo MATCHES) # OK

问题:

Tip of the hat to Fólkvangr https://stackoverflow.com/users/9657437/f%c3%b3lkvangr for his input.

A literal RHS of =~是按设计解析的不同地比不带引号的标记作为参数,在尝试让用户专注于转义字符just为了regex,也不必担心平常的shell未加引号的标记中的转义规则。

例如,

[[ 'a[b' =~ a\[b ]] && echo MATCHES  # OK

匹配,因为\被_传递到正则表达式引擎(也就是说,正则表达式引擎也看到literal a\[b),而如果您使用相同的不带引号的标记作为常规参数,则通常的外壳扩展 http://www.gnu.org/software/bash/manual/html_node/Shell-Expansions.html#Shell-Expansions应用于未加引号的标记会“吃掉”\,因为它被解释为shell转义字符:

$ printf %s a\[b
a[b  # '\' was removed by the shell.

然而,在这样的背景下=~这次特殊的穿越\仅适用于以下字符之前regex元字符通过他们自己,定义为ERE(扩展正则表达式)POSIX 规范 https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_04_03(为了躲避他们对于正则表达式,以便将它们视为literals:
\ ^ $ [ { . ? * + ( ) |
相反,这些正则表达式元字符可能会被例外地使用unquoted- 确实must不被引用以拥有其特殊的regex含义 - 尽管大多数通常需要\-转义未加引号的标记以防止shell从解释它们。
Yet, a subset of the shell元字符do仍然需要逃避,因为shell's sake,以免破坏语法[[ ... ]]有条件:
& ; < > space
因为这些角色也不是regex元字符,不需要在正则表达式方面也支持转义它们,因此,例如,正则表达式引擎看到\&在 RHS 中就像&工作正常。

For any other前面的字符\, 贝壳removes the \在将字符串发送到正则表达式引擎之前(就像在正常 shell 扩展期间所做的那样),这是不幸的,因为然后甚至是 shell 中的字符doesn't认为特殊不能传递为\<char>到正则表达式引擎,因为 shell 总是将它们作为<char>.
E.g, \b总是被视为只是b由正则表达式引擎。

因此,目前不可能使用以下形式的(根据定义非 POSIX)正则表达式构造:\<char> (e.g., \<, \>, \b, \s, \w, \d, ...) 按字面意思,不加引号=~ RHS, 因为任何形式的转义都不能确保这些构造被regex发动机本身,经过解析后shell:

既然两者都没有<, >, nor b are regex元字符,外壳removes the \ from \<, \>, \b(如常规 shell 扩展中所发生的那样)。因此,通过\<word\>例如,使正则表达式引擎看到<word>,这不是本意:

  • [[ '<word>' =~ \<word\> ]] && echo YES匹配,因为正则表达式引擎看到<word>.
  • [[ 'boo' =~ ^\boo ]] && echo YES匹配,因为正则表达式引擎看到^boo.

Trying \\<word\\> breaks该命令,因为shell对待每一个\\作为一个逃亡者\,这意味着元字符<然后考虑unquoted,导致语法错误:

  • [[ ' word ' =~ \\<word\\> ]] && echo YES导致语法错误。
  • This wouldn't happen with \\b, but \\b is passed through (due to the \ preceding a regex metachar, \), which also doesn't work:
    • [[ '\boo' =~ ^\\boo ]] && echo YES匹配,因为正则表达式引擎看到\\boo,与文字匹配\boo.

Trying \\\<word\\\>- 由normalshell 扩展规则导致\<word\> (try printf %s \\\<word\\\>) - also不起作用:

  • 发生的情况是外壳eats the \ in \<(同上对于\b和别的\-前缀序列),然后传递前面的\\到正则表达式引擎as-is(再次,因为\在a之前被保留regex元字符):

  • [[ ' \<word\> ' =~ \\\<word\\\> ]] && echo YES匹配,因为正则表达式引擎看到\\<word\\>,与文字匹配\<word\>.

简而言之:

  • Bash 的解析=~ RHS literals设计与单字符考虑到正则表达式元字符,并且不支持多字符开头的构造\, 例如\<.

    • 因为 POSIX ERE 不支持这样的构造,=~如果您将自己限制在此类正则表达式中,则可以按设计工作。

    • 然而,即使在这种限制下,由于需要混合正则表达式相关和 shell 相关,设计也有些尴尬\-转义(引用)。

    • Fólkvangr 在 Bash FAQ 中找到了官方的设计原理here http://git.savannah.gnu.org/cgit/bash.git/tree/doc/FAQ#n1927,然而,它既没有解决所说的尴尬,也没有解决缺乏支持(总是非 POSIX)\<char>正则表达式构造;它确实提到使用辅助。然而,变量作为一种解决方法,尽管只是为了使其更容易表示空白.

  • 如果正则表达式引擎应该看到的字符串是通过variable或通过a的输出命令替换,如上所示。


可选读物:便携式仿真使用符合 POSIX 的 ERE(扩展正则表达式)进行字边界断言:

  • (^|[^[:alnum:]_])代替\< / [[:<:]]

  • ([^[:alnum:]_]|$)代替\> / [[:>:]]

Note: \b不能用单个表达式来模拟 - 在适当的地方使用上面的表达式。

潜在的警告是上述表达式也将capture匹配的非单词字符,而 true断言例如\< / [[:<:]]也不要。

$foo = 'myword'
[[ $foo =~ (^|[^[:alnum:]_])myword([^[:alnum:]_]|$) ]] && echo YES

上面的匹配,符合预期。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

bash 支持字边界正则表达式吗? 的相关文章

  • Perl:Chomping字符串后,它不打印字符串的值

    所以我目前正在尝试编写一个 perl 脚本来读取一个文件并写入另一个文件 目前 我遇到的问题是从解析的行中删除换行符 我输入这样的文件 BetteDavisFilms txt 1 Wicked Stepmother 1989 as Mira
  • 删除删除线的 unicode 文本?

    我偶尔会收到用户的输入 他们正在使用那些烦人的 stikethrough 文本生成器 这破坏了我的代码 我尝试过在这里找到的一些代码 string preg replace x00 x1F x80 xFF string 它有效 但我需要它只
  • 用于匹配 Liquid 模板中标签的正则表达式:html 标签内的“">”

    我必须在 Liquid 模板中为 body 标签编写匹配模式 虽然匹配 HTML 标签非常简单 但我遇到了 HTML 特殊字符可以在 Liquid 代码中使用的问题 例子 或简化
  • 通过 JMeter 正则表达式解析 HTML

    我在 JMeter 中的正则表达式方面遇到一些问题 我有这个 HTML 表单
  • 正则表达式匹配埃及象形文字[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我想知道一个匹配埃及象形文字的正则表达式 我完全一无所知 需要你的帮助 我无法发布这些字母 因为堆栈溢出似乎无法识别它 那么谁能告诉我这些
  • bash后台进程修改全局变量

    在我的 Bash 脚本中 我有一个全局变量foo设置为某个值和函数过程back func这是在后台运行的 我希望后台进程能够访问foo并修改其值 以便主进程可以看到变化 我的脚本的结构如下 bin bash foo 0 function b
  • C# 使用正则表达式获取内容内的 html 标签和下一个元素

    这是我的html div class 50f3 Followed by a href https www facebook com zurabj followers 7 583 people a div div class 50f3 Fri
  • 将文本拆分为句子[重复]

    这个问题在这里已经有答案了 我希望将文本分成句子 谁能帮我 我还需要处理缩写 然而 我的计划是在早期阶段更换它们 先生 gt 先生 import re import unittest class Sentences def init sel
  • 相当于 Python 中的 set -o pipelinefail 吗?

    我有一些 Python 脚本 每个脚本都大量使用排序 uniq ing 计数 gzipping 和gunzipping 以及 awking 第一次运行我使用的代码subprocess call 是的 我知道安全风险 这就是为什么我说这是第一
  • 从Python中的字符串中删除重复行

    我在 python 中有一个字符串 并且想删除重复的行 即当 n 之间的文本相同时 然后删除第二个 第三个 第四个 出现的地方 但保留字符串的顺序 例如 line1 n line2 n line3 n line2 n line2 n lin
  • 在 bash tee 中,正在将函数变量设置为本地函数,我该如何逃避这个问题?

    我一直坚持使用 bash scipt 它应该同时写入标准输出和文件 我正在使用函数和其中的一些变量 每当我尝试将函数重定向到文件并用 tee 在屏幕上打印时 我无法使用在函数中使用的变量 因此它们以某种方式变成本地变量 这是一个简单的例子
  • Java 文件扩展名正则表达式

    我试图提出一个 Java 正则表达式 只有当文件名具有有效的扩展名时 它才会匹配文件名 例如 它应该匹配 foo bar 和 foo b 但都不匹配 foo 也不是 foo 我编写了以下测试程序 public static void mai
  • 在Unix下,判断执行该程序的用户是否是root?

    我正在编写一个 rake 脚本 并希望检测 如果可能的话 使用 Ruby 而不是 bash 执行 rake 脚本的用户是否具有 root 权限 如果它不是 root 那么我想终止脚本 Use uid http www ruby doc or
  • 我可以使用 GIT_CONFIG 环境变量来为所有 git 命令使用配置文件吗

    我一直在尝试使用 git 配置文件export GIT CONFIG
  • 正则表达式需要 10 位数字而不考虑空格

    我需要一个正则表达式将数字限制为 10 即使有空格也是如此 例如它允许06 15 20 47 23与0615204723 我试过 d 10 但是如何忽略空格 另外 数字应该以06 or 07 编者注 最后一个要求来自OP的评论 这将在大多数
  • 用任意数量的逗号和空格分割字符串

    我有一个字符串 我试图将其转换为列表 但我得到空条目 A B C D returns A B C D 我想删除所有 空 逗号 A B C D 我想 current split s 这不会产生我想要的结果 我应该使用什么正则表达式 您需要两步
  • 正则表达式:替换字符串中第一次出现的字符

    我有这个字符串 ABCDE 某事某事 XYZ 0 JKLM 0 某事某事 some value 仅将第一个冒号 替换为下划线 的正则表达式是什么 在标准系统中 您只需编写 s 要实现全局替换 用下划线替换冒号的每个实例 您需要在替换后添加一
  • 递归触摸修复计算机之间的同步[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 由于我的错误 我正在寻找一种从命令行触摸目录 和子目录 中的每个文件的方法 我的同步存储库在我的开发机器上有点不同步 我现在已经通过一些令人不快的巫术
  • Javascript 搜索并替换包含方括号的字符序列

    我正在尝试在字符串 Nationality EN ESP 中搜索 EN 我想从字符串中删除它 所以我使用替换方法 代码示例如下 var str Nationality EN ESP var find EN var regex new Reg
  • 使用 tac 和 sed 反转文件

    我有一个用例 我需要搜索并替换文件中最后一次出现的字符串并将更改写回文件 下面的案例是该用例的简化版本 我正在尝试反转该文件 进行一些更改 再次将其反转并写入该文件 我为此尝试了以下代码片段 tac test sed s a b sed i

随机推荐

  • 引用 url() 的值真的有必要吗?

    我应该在样式表中使用以下哪一项 Example 1 background image url image png Example 2 background image url image png Example 3 background i
  • UISlider不会自动重绘

    我的应用程序上有一个 UISlider 有时我不仅需要更新它的值 还需要更新它的minimumValue 值已更改 但如果我调用 setValue 方法或为滑块分配新值 它会具有新值 但滑块不会将自身重新绘制到该新值应有的位置 我怎样才能重
  • 将productFlavor添加到实验性Android gradle插件库

    我有一个使用实验性 gradle 插件的项目 即0 2 0 当我没有了productFlavor 我可以在Android Studio中完美集成一个库模块 一切都运行良好 但是当图书馆有一个productFlavor 我的主项目没有找到库类
  • 获得新的 access_token 后,如何更新我的 cookie?

    使用刷新令牌获取新的访问令牌后 我想使用该访问令牌更新我的客户端 cookie 我的客户端能够使用 ajax 登录并调用我的 REST API 但是当第一次授权过期时 API 调用自然不再起作用 我有一个 NET Web 应用程序 它使用自
  • 在Linux上编译C# + WPF以便在Windows上运行

    我有一个 C 应用程序 其中某些部分是使用 WPF 编写的 Mono 不支持 可以在 Linux 上编译这个应用程序吗 最终 该应用程序将在 Windows 上运行 但它是更大框架的一部分 并且我们的整个构建过程在 Linux 上运行 因此
  • 从捆绑包中检索 android.intent.extra.EMAIL 值

    我创建了一个应用程序 例如电子邮件客户端应用程序 例如Gmail 当用户单击其他应用程序中的电子邮件地址并从列表中显示的电子邮件发送应用程序中选择我的应用程序时 电子邮件内容 例如电子邮件地址 电子邮件主题等 有意进入我的应用程序 但问题是
  • PHP:STR 替换为链接

    我有这个 PHP 聊天框 如果我在聊天框中键入链接 它不会将其显示为链接 我如何使用 STR 替换来执行此操作 它应该响应诸如 http http com nl www www 之类的内容 我的其他 STR 替换行如下所示 bericht
  • 对于 AWS Kinesis 的 KCL Java 库,如何使用 requestShutdown 和 shutdown 正常关闭

    我正在尝试使用 Java 中 KCL 库的新功能来实现 AWS Kinesis 的正常关闭 方法是注册关闭钩子以停止所有记录处理器 然后正常停止工作进程 新库提供了记录处理器需要实现的新接口 但它是如何被调用的呢 尝试先调用worker r
  • 在 JavaScript 中对字符串使用除法运算符 (/)

    我意识到在javascript中所有101 100 101 100 101 100 和 101 100 结果都是1 01 在Chrome FF和IE11上检查 但我找不到有关此行为的文档 因此我的问题是使用此功能是否 跨浏览器 安全 以及这
  • Matlab 图像数据的 hist 函数

    我是 Matlab 新手 我想制作自己的函数 与 imhist 显示图像数据的直方图 完成相同的工作 但我对此完全是新手 我不知道如何做开发这样的功能 我开始做一些东西 但它非常不完整 function output args myhist
  • SQL Server中的列级与表级约束?

    A 列级 GO CREATE TABLE Products ProductID INT CONSTRAINT pk products pid PRIMARY KEY ProductName VARCHAR 25 GO b 表层 CREATE
  • C# WinForms:使用一个或多个附加线程进行绘图。如何?

    如果我有一张包含各种几何形式 直线 矩形 圆形等 的大图 线程需要花费大量时间来绘制所有内容 但在现实生活中 一栋建筑是由不止一名工人建造的 因此 如果绘图是建筑物而线程是构建者 则绘制速度会快得多 但我想知道怎么做 你能告诉我怎么做吗 有
  • 用 Pandas 计算该月的最后一个星期五

    我编写了这个函数来获取该月的最后一个星期四 def last thurs date date month date dt month year date dt year cal calendar monthcalendar year mon
  • 同一页面上具有不同ajax源的多个DataTable

    我在一个页面上有几个表格 使用数据表 http datatables net 每个都需要有自己的 sAjaxSource 我似乎无法确切地弄清楚如何做到这一点 这是我拥有的最少代码 var oTable datatable dataTabl
  • 将数组从 Flash (AS3) 发送到 JavaScript

    是否可以使用ExternalInterface 调用将数组从Flash AS3 发送到JavaScript 我目前正在 Flash 内的 foreach 循环中多次调用一个函数 但速度太快 JavaScript 无法跟上 我的想法是创建一个
  • C++ 装饰器模式,模板的静态多态性和注册回调方法

    我正在尝试使用静态多态性来创建装饰器模式 至于为什么我不使用动态多态 请看这个QA https stackoverflow com questions 39312070 c dynamic cast over decorator insta
  • 在脚本标签内工作的角度表达式

    如何在脚本标签内使用角度表达式 我对此很陌生并且需要帮助 这是我的 java 脚本代码的示例
  • Python中两个元组中的元素之间的组合[重复]

    这个问题在这里已经有答案了 我有两个元组 t1 A B t2 C D E 我想知道如何在元组之间创建组合 所以结果应该是 AC AD AE BC BD BE EDIT Using list itertools combinations ab
  • Ruby 中的任务/未来

    代表潜在延迟的异步计算并且可以订阅其完成的模式的惯用 Ruby 模拟是什么 即类似于 NET 的东西System Threading Task 或Python 3 xconcurrent futures future 请注意 这并不一定意味
  • bash 支持字边界正则表达式吗?

    我试图在再次添加该单词之前匹配列表中是否存在该单词 以避免重复 我正在使用 bash 4 2 24 并尝试以下操作 foo bmyword b also foo