【问题标题】:Find the first name that starts with any letter than S using regex使用正则表达式查找以 S 以外的任何字母开头的名字
【发布时间】:2021-08-11 13:06:35
【问题描述】:

我是正则表达式的新手,我正在尝试从文本文件中查找仅以 S 开头的姓氏,后跟逗号,然后是空格,然后是不以 S 开头的名字。 我在 MacBook 上使用终端。

这是我的正则表达式

^[S\w][,]?[' ']?[A-RT-Z]?

我的全部命令

猫人.txt | grep -E ^[S\w][,]?[' ']?[A-RT-Z]?

名字是第二个单词,姓氏是每行的第一个单词。

我得到的结果:

施密特,保罗

出售,西蒙

史密斯,彼得

斯蒂芬斯,希拉

我期望得到什么

施密特,保罗

史密斯,彼得

【问题讨论】:

  • 您使用的是grepawksedperlpythoned 还是别的什么?如果是grepgrep 有哪些选项?最好显示您正在使用的命令行。字符类中重复的单引号名义上是不相关的(字符类[aba][ab] 相同)。但是单引号(和双引号)在 shell 中很重要。 \w 表示法在 PCRE(Perl 兼容的正则表达式)中具有特殊含义,但在其他地方没有。
  • 我正在使用 grep。这是我的完整命令:: cat People.txt | grep -E ^[S\w][,]?[' ']?[A-RT-Z]?
  • 请查看UUoC — Useless Use of cat — 并使用grep -E '…regex…' People.txt 处理文件。请注意,我的大纲将整个正则表达式括在单引号中——强烈建议这样做,因为它可以防止不必要的 shell 扩展/元字符处理。然后,您将不需要空间周围的内部单引号。您不需要逗号周围的字符类(尽管它不会造成重大伤害)。如所写,您的正则表达式会查找以 Sw 开头的行(shell 会为您删除反斜杠)。
  • 您在问题中编辑的命令行与您的评论中显示的命令行不匹配。它们中的任何一个都准确吗?
  • @JonathanLeffler 实际上它工作得很好。感谢您提供给我的链接,这对我很有帮助。 cmets 中的那个是我将编辑我的问题的准确的那个。

标签: regex grep


【解决方案1】:

在 shell 脚本(或终端)中编写正则表达式的第一条规则是“将正则表达式括在单引号中”,这样 shell 就不会尝试解释正则表达式中的元字符。如果您需要匹配单引号但不匹配双引号,或者如果您需要插入变量但旨在使用单引号,则有时您可能会使用双引号而不是单引号。另外,避免UUoC — Useless Use of cat

您的问题目前显示两个正则表达式:

^[S\w][,]?[' ']?[A-RT-Z]?

cat People.txt | grep -E ^[S\w][,]?[' ']?[P\w+]?

如果按照建议编写,这些将变为:

grep -E -e '^[Sw],? ?[A-RT-Z]?' People.txt
grep -E -e '^[Sw],? ?[Pw+]?' People.txt

shell 会删除您的演绎版中的反斜杠。字符类中的+ 匹配一个加号。您不需要逗号周围的方括号(尽管它们不会造成重大伤害)。我使用-e 选项来明确性,因此在通过历史记录编辑命令时,我可以在正则表达式(-w-l-n 或...)之后添加额外的参数。 (我也不喜欢在非选项参数之后识别选项;我经常在我的环境中设置$POSIXLY_CORRECT。这是个人的怪癖。)

两个命令中的第一个查找以Sw 开头的行,后跟可选的逗号、可选的空格和可选的除S 之外的大写字母。第二个类似,只是它查找可选的Pw。这些都与问题没有太大关系。

您需要一个更像以下之一的表达式:

grep -E -e '^[S][[:alpha:]]*, [^S]' People.txt
grep -E -e '^[S][a-zA-Z]*, [^S]' People.txt

这些允许使用单个字符的名称(仅 S),但您可以使用 + 而不是 * 来要求一个或多个字母。

可能有很多改进,具体取决于您想要工作的程度,但主要工作是查找“行中的第一个单词以 S 开头,然后是逗号、空格和第二个单词不以S'开头。

给定一个文件People.txt,其中包含:

Randall, Steven
Rogers, Timothy
Schmidt, Paul
Sells, Simon
Smith, Peter
Stephens, Sheila
Titus, Persephone
Williams, Shirley
Someone
S

您的正则表达式产生输出:

Schmidt, Paul
Sells, Simon
Smith, Peter
Stephens, Sheila
Someone
S

我的命令产生:

Schmidt, Paul
Smith, Peter

【讨论】:

    【解决方案2】:

    这样的事情似乎可以正常工作:

    ^S.*, [^S].*$
    
    • ^S.* - 必须以 S 开头并开始捕获所有内容
    • , [^S] - 前导逗号、空格,而不是 S
    • .*$ - 捕获字符串的其余部分

    https://regex101.com/r/76bfji/1

    【讨论】:

    • 我在终端中这样写,我仍然得到相同的结果 grep -E ^[S.*,][^S].*$ People.txt。我是不是搞错了?
    • @KarimOsama 你为什么不使用我提供的正则表达式?
    • 我在你写的不带括号的情况下再次尝试,它工作正常。谢谢
    猜你喜欢
    • 1970-01-01
    • 2015-10-10
    • 1970-01-01
    • 2015-05-14
    • 2017-07-09
    • 2021-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多