使用标准命令行工具提取关键字?

Yimin Rong

例如,根据Wiktionary,这是“ when”的发音。enPR,IPA和X-SAMPA是用于显示发音的不同方案。

when:* {{a|US}} {{enPR|wĕn|hwĕn}}, {{IPA|/wɛn/|/ʍɛn/}}, {{X-SAMPA|/wEn/|/WEn/}}

我想提取该关键字when及其两个IPA发音,并将它们放在单独的行上:

when wɛn
when ʍɛn

一个单词可能有一个,两个或多个IPA发音,并且可能有也可能没有enPR或X-SAMPA发音。

我在考虑PHP,列表中的列表,但这似乎是过大了,并且我不希望用户必须安装它。有没有办法在awk,sed,cut或其他标准Unix命令行实用程序中执行此操作?

斯蒂芬·查泽拉斯(Stephane Chazelas)

使用sed,您可以将其编写为:

sed '/\([^:]*\):.*{IPA|\([^}]*\).*/!d;s//\1 \2/;s,/,,g;:1
     s/\(\([^ ]*\).*\)|/\1\n\2 /;t1'

细目分类(@slm,谢谢)

上面的命令可以分解如下:

  1. 解析输入when: ... {IPA|...}并删除不匹配的行。

    /pattern/!d; s//repl/

    我们[d]放弃与模式不匹配的行,然后在下一个[s]替换命令中重复使用相同的模式(空模式意味着重用最后一个模式)。代替[d]删除不匹配的行,我们可以通过使用b而不是使它们保持不变d,或者如果我们知道所有行都与模式匹配,则可以s/pattern/repl/直接使用

    /\([^:]*\):.*{IPA|\([^}]*\).*/
    

    该模式将数据分为2个块​​。第一块是when:这段代码\([^:]*\):说要取走所有字符,直到遇到a为止,:并暂时保存它。变数(\1)。

    :最高到(包括)之间的所有字符{IPA|被跳过。所保存的下一位是IPA|之后的所有内容这是通过此代码块来完成的,该代码块\([^}]*\)表示保存所有代码,直到}遇到a。这保存在变量(\2)中。

    注意:sed任何时候要保存字符串的大部分内容时,都可以将其包装在括号中。他们需要使用a进行转义,以\使sed您知道这并不是字面上的括号。像这样:\( savethis \)

    例子

    $ sed 's/\([^:]*\):.*{IPA|\([^}]*\).*/\1 \2/;' sample.txt
    when /wɛn/|/ʍɛn/
    
  2. 删除所有正斜杠(/

    这看起来更复杂,因为它使用了备用分隔符。您通常会使用form s///g,但是sed让我们即时创建分隔符,所以我们使用逗号代替(s,,,g)。该块搜索/并将其替换为空。

    例子

    $ sed '/\([^:]*\):.*{IPA|\([^}]*\).*/!d;s//\1 \2/;s,/,,g;' sample.txt
    when wɛn|ʍɛn
    
  3. 遍历每个IPA

     :1 s/\(\([^ ]*\).*\)|/\1\n\2 /;t1
    

    到目前为止,这是此解决方案中最复杂的部分。很难知道发生了什么,但是此块是一个有条件的分支。

     :label command(s) t label
    

    该标签是:1在指令(或多个)s/\(\([^ ]*\).*\)|/\1\n\2 /;t label是“测试”的是看到如果前面的命令修改的模式空间。如果是这样,则跳转到标签1,因此t1

  4. 循环内的命令

    如果我们花label ... loop一秒钟时间,然后增加IPA示例,使其具有3个,则可以看到发生了一些变化。

    {{IPA|/wɛn/|/ʍɛn/|/blah/}}
    

    到此为止,我们将使用先前的命令结束此操作。

    when wɛn|ʍɛn|blah
    

    如果我们现在运行此命令:

    $ echo "when wɛn|ʍɛn|blah" | sed 's/\(\([^ ]*\).*\)|/\1 \2 /;'
    

    我们得到这个:

    when wɛn|ʍɛn
    when blah
    

    您能看到它现在在做什么吗?是的,我也没有,所以让我们简化一点,取出换行符(\n)并交换一些较短的字符串。

    简单的例子

    $ echo "X C1|C2|C3" | sed 's/\(\([^ ]*\).*\)|/\1 \2 /;'
    X C1|C2 X C3
    

    现在,这里发生的事情是代码\(\([^ ]*\).*\)|很聪明,因为它嵌套了括号,以便它们像这样( ( ) )内部括号中匹配的是没有空格的任何东西。这就是when字符串。外部parse匹配所有内容,直到最后一个管道(|)。

    此代码段的另一个有趣之处是,对括号进行排序,以便将外部的存储在\1内部而将内部的存储在内部\2这是因为sed根据遇到它们的顺序对它们进行编号。

    您可以通过使用附加\1的和扩展代码片段来使自己相信这一点\2

    $ echo "X C1|C2|C3" | sed 's/\(\([^ ]*\).*\)|/\1 \1 \1 /;'
    X C1|C2 X C1|C2 X C1|C2 C3
    
    $ echo "X C1|C2|C3" | sed 's/\(\([^ ]*\).*\)|/\1 \2 \2 /;'
    X C1|C2 X X C
    

    因此,循环内的命令基本上要花X2倍的时间。一次作为整体的一部分X C1|C2(外部括号),第二次作为直至空间的任何内容(内部括号)。

  5. 返回条件分支

    好的,因此分支基本上将在#5中调用该命令,因为IPA的数目超过2。sed分支构造将继续重新运行该命令,直到该命令不再修改替换为止,然后该命令停止。

    例子

    $ echo "X C1|C2|C3" | sed ':1 s/\(\([^ ]*\).*\)|/\1\n\2 /; t1'
    X C1
    X C2
    X C3
    

希望以上内容能在将来对其他路人有所帮助。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

命令行中的关键字“ python”和“ python3”有什么区别?

如何将None关键字作为命令行参数传递

如何在命令行上强制解释为关键字而不是别名?

无论python关键字如何,如何获取python中命令行参数的数量?

无法在DyanmoDB命令行中处理reserver关键字“ Key”

使用标准命令行工具解析命令输出中的所有IP地址

使用scrapy从metatag提取关键字

有什么办法可以从Linux命令行中找到有关C关键字的信息?

使用标准linux命令行工具修改二进制文件中的字节

使用命令行工具过滤并满足数据包流标准

MAUI关键字提取:找不到命令

使用 ExtractText 命令行工具时提取错误的空格字符

命令行工具列出当前设置的套接字选项

如何在机器人框架中参数化 Open Browser 关键字以从命令行无头运行?

命令行差异工具

从列表中提取关键字,然后使用和

VBA - 使用关键字对子组提取进行分组

使用Lucene提取关键字时出错

使用 Postgres 从文本中提取关键字

尝试使用Golang在命令行上解析标准输出

如何在Windows 7中使用命令行工具从HOSTS文件中提取条目?

使用命令行工具下載 Excel 文件

使用 cro 命令行工具时出现问题

使用命令行工具从GitHub获取源文件?

易于使用的命令行wifi /网络工具

获取鱼壳以使用gcloud命令行工具?

节点:ShellJS无法使用命令行工具

使用Swift命令行工具进行颜色输出

BigQuery命令行工具-使用查询追加到表