正则表达式 - 在终端上找不到命令

正则表达式 - 在终端上找不到命令

我正试图抓住我的名字 369从 file.txt 我用正则表达式输入了这个 grep 行,但它返回一个错误。我尝试过使用egrep,但没有成功。

输入:

  1. 我的名字 369 == 匹配
  2. 我的名字 161 == 匹配
  3. my_name 123 2 != 错误

错误: ?!.: command not found

这是我要执行的代码并且它有效正则表达式101

grep -i "^\s*my_name\s+[0-9]+\s*$(?!.)*" file.txt

答案1

看起来你想要:

grep -Ex '[[:space:]]*my_name[[:space:]]+[0123456789]+[[:space:]]*' file.txt
  • 在双引号内,$(cmd)它扩展为 的输出cmd,称为命令替换仍在执行。在这里,您试图获取?!.命令的输出,但该命令不存在,因此会出现错误。由于许多正则表达式运算符碰巧在 shell 中也具有特殊含义,因此最好使用单引号来引用它们,因为它们会转义每一个shell 的字符。
  • \s并且(?!.)珀尔正则表达式运算符。虽然现在有些grep实现确实支持\s(作为标准的缩写形式[[:space:]]),但它们不能支持(?!.)负向前看运算符,因为(?!需要匹配文字,(?!因为它自grep70 年代初引入以来一直如此。他们可以使用-E(由 POSIX 在 90 年代初引入)来识别它,因为标准扩展正则表达式 (ERE)(?...未指定。 East-open 的实现grep就是这样做的,但这是我所知道的唯一一种。无论如何,在 后面添加任何内容$(旨在匹配主题末尾)是没有意义的。*在环视运算符之后添加量词(在您的情况下)也是没有意义的。
  • +是 ERE 或 Perl RE 运算符,而不是 BRE 运算符。 BRE 等效项是\{1,\}.
  • [0-9]确实匹配 0123456789 ASCII 阿拉伯数字,但通常有更多(通常与数字相关)字符恰好在 0 和 9 之间排序。如果(就像进行输入验证时一样)您只想匹配 0123456789,则需要指定确切的列表。
  • 添加-x以匹配整个线可以节省使用^$锚点的麻烦。
  • -i用于不区分大小写的匹配。有了它,MY_NAME,My_NaMe也会被接受。
  • -E在上面使用只是因为+打字比\{1,\}只是装饰性的要短。此处使用 ERE 并不是绝对必要的。
  • do的某些实现grep支持-P使用类似 Perl 的正则表达式进行匹配的选项。有了这些,你就可以做到grep -Px '\s*my_name\s+\d+\s*'\d旨在匹配十进制数字。在我尝试过的GNU版本中grep,它只匹配0123456789,但我不能保证所有版本和实现都是如此。例如,请参阅grep -Px '(*UCP)\d'(对于UnicodeC字符属性)如何P匹配更多十进制数字字符。为了安全起见,您可能仍然想在[0123456789]那里使用。

另一种方法是使用awk并执行:

awk 'NF == 2 && $1 == "my_name" && $2 ~ /^[0123456789]+$/'

为了更清楚地指定您想要具有两个字段(其中N字段数F为 2)的行,第一个字段是my_name,第二个字段仅由 ASCII 十进制数字组成。默认情况下,字段用空格分隔(更像是[[:blank:]]),尽管某些awk实现仅考虑空格和制表符,有些还考虑垂直间距字符,例如[[:space:]]/ \sdo。

对于不区分大小写的匹配,你会这样做tolower($1) == "my_name"。 GNU 实现awk可以通过传递 来对所有正则表达式匹配进行不区分大小写的匹配-v IGNORECASE=1


1 从技术上讲,?!.它是一个 shell glob,也是?一个 glob 运算符。因此,如果当前工作目录中有被调用的文件a!.b!.那么该文件将扩展到这些文件,并且您将尝试使用作为参数执行a!.命令。b!.使用 zsh 或 Fish 等更理智的 shell(另请参阅failglob中的选项),当它与任何文件都不匹配bash时,您会收到错误消息。?!.

相关内容