【问题标题】:How to extract only URLs that contains subdomains如何仅提取包含子域的 URL
【发布时间】:2018-08-18 13:08:10
【问题描述】:

我的原始文件包含:

mail.google.com
srv1.mail.google.com
google.com
facebook.com
yahoo.com
tt.twitter.com
yy.notexist

我想提取包含子域的行。分别是:

mail.google.com
srv1.mail.google.com
tt.twitter.com

我试过这个正则表达式:

grep -P '^.[^.]+\.(.[^.])+\..[^.]+$' test.csv

但它只给出:

mail.google.com

我不明白为什么它看不到其余部分。我不确定我的正则表达式是否完美并捕获所有情况。我不确定如何表达(除了点以外的任何字符),我使用^.[^.] 在正则表达式中表达它。你能纠正我吗?

【问题讨论】:

  • 查看here 当有人回答您的问题时该怎么办。

标签: regex linux search grep


【解决方案1】:

根据给定的样本输入/输出回答,没有智能来区分什么是顶级域

$ awk -F. 'NF>2 || $NF!="com"' ip.txt
mail.google.com
srv1.mail.google.com
tt.twitter.com
yy.notexist

$ # any domain, not just .com
$ awk -F. 'NF>2' ip.txt
mail.google.com
srv1.mail.google.com
tt.twitter.com
  • -F. 设置 . 为输入字段分隔符
    • 某些版本可能需要-F'[.]' 而不是-F.
  • NF>2 || $NF!="com" 打印行,如果它有超过 2 个字段或者最后一个字段不是 com


grep

$ grep -xv '[^.]*\.com' ip.txt
mail.google.com
srv1.mail.google.com
tt.twitter.com
yy.notexist

$ # any domain, not just .com
$ grep -xv '[^.]*\.[^.]*' ip.txt
mail.google.com
srv1.mail.google.com
tt.twitter.com
  • -x 只匹配整行
  • -v 打印与给定正则表达式不匹配的行
  • [^.]*. 字符
  • \.com 匹配 .com

【讨论】:

  • grep 模式将打印任何文本行,例如random text
  • true,如前所述,这是基于给定的样本,没有内置任何智能...
  • 实际上awk -F'[.]' 'NF>2' ip.txt 有效,但是awk -F'[.]' 'NF>2 || $NF!="com"' ip.txt 打印所有内容
  • 在这种情况下,你可能有dos风格的行尾,检查cat -v grepdomain.txt
【解决方案2】:

您可以使用以下表达式:

^(?:(?:[a-z0-9]+.){2,}com|[a-z0-9]+(?!.com).[a-z]+)$

正则表达式分解:

  • ^ 字符串开头。
  • (?: 非捕获组。
    • (?:[a-z0-9]+\.){2,}com 非捕获组,匹配小写字母或数字,后跟句号。该模式重复超过 2 次或更多次。之后匹配com
    • | 交替,俄勒冈州。
    • [a-z0-9]+(?!\.com)\.[a-z]+ 小写字母或数字,后跟.com,后跟. 和字母字符。
  • )关闭非捕获组。
  • $ 字符串结束。

命令:

grep -P '^(?:(?:[a-z0-9]+\.){2,}com|[a-z0-9]+(?!\.com)\.[a-z]+)$' test.csv

打印:

mail.google.com
srv1.mail.google.com
tt.twitter.com
yy.notexist

编辑:

根据您的编辑,使用:

^(?:[a-z0-9]+.){2,}com$.

命令:

grep -P '^(?:[a-z0-9]+\.){2,}com$' test.csv

打印:

mail.google.com
srv1.mail.google.com
tt.twitter.com

【讨论】:

  • 标签的数量表明某事物是否是子域的假设过于简单化了。在各自的层次结构中,arizona.edugoogle.co.ingreatneck.k12.ny.us 是顶级域。
  • 也许 OP 没有选择正确的词。我的回答从他分享的信息中解决了 OP 的问题。
  • @UnbearableLightness 我觉得你的回答太复杂了。我的要求是我只是在寻找似乎有子域的行。如果是example.com,则不包含子域。如果它是这样的:(sub.)+example.com,那么它包含子域,其中 (sub)+ 可以重复一次或多次。我将在另一个阶段使用一些 python 库来确定我们的主域。我的问题只是以(sub)+.example.com 格式提取这些行。
  • 我觉得你的答案太复杂了它有效,我不明白你的意思。
  • 我相信你可以通过其他方式做到这一点,但使用重复的非捕获组更简洁。你的正则表达式是错误的,我给了你一个可行的解决方案。在我看来,必须这样做,否则您将永远无法处理可变数量的子域。
【解决方案3】:

您只得到 1 个匹配项,因为您的正则表达式将匹配由 2 个点分隔的 3 个部分,因此不会匹配:

srv1.mail.google.com
google.com
facebook.com
yahoo.com

您不匹配 tt.twitter.com 因为这部分 (.[^.])+\. 将捕获重复一次或多次匹配单个字符后跟不匹配点的组,每次重复匹配 2 个字符后跟文字点.

例如,这将不匹配 twitter.,因为它包含 7 个字符和一个点,并且重复是每 2 个,因此 twitte. 将匹配。

您似乎不想匹配至少由 2 个点分隔的点。如果您想保持模式 [^.]+ 不匹配点,您可以使用:

grep -P '^[^.]+(?:\.[^.]+){2,}$' test.csv

这将匹配:

  • ^断言字符串的开始
  • [^.]+ 一次或多次不匹配一个点
  • (?:\.[^.]+){2,} 至少重复 2 次的非捕获组匹配一个文字点,然后不是一个点一次或多次
  • $断言字符串结束

【讨论】:

    【解决方案4】:

    我可以通过以下命令实现我的问题提出的要求:

    grep -P '^[^.]+\.([^.]+\.)+[^.]+'
    

    识别具有多个点的 URL 是一种简单的命令,这意味着它们具有子域。但是,这不会区分 uni.ac.uk 是主域还是子域。理想情况下,另一个处理阶段是使用具有更先进技术的库之一来从具有多个点的 URL 中识别主要域。这些库的一个例子是tldextract

    【讨论】:

      猜你喜欢
      • 2012-02-12
      • 1970-01-01
      • 2017-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-27
      • 2018-02-06
      相关资源
      最近更新 更多