【问题标题】:Grep/Sed/Awk OptionsGrep/Sed/Awk 选项
【发布时间】:2017-08-28 14:20:06
【问题描述】:

您如何使用 grep 或使用 sed 或 awk 来解析动态长度的子字符串?下面是一些例子:

我需要解析这些字符串中除了“XXXXX.WAV”之外的所有内容,但这些字符串不是固定长度。

有时候是这样的:

{"filename": "/assets/JFM/imaging/19001.WAV"},
{"filename": "/assets/JFM/imaging/19307.WAV"},
{"filename": "/assets/JFM/imaging/19002.WAV"}

有时像这样:

 {"filename": "/assets/JFM/LN_405999/101.WAV"},
 {"filename": "/assets/JFM/LN_405999/102.WAV"},
 {"filename": "/assets/JFM/LN_405999/103.WAV"}

是否有一种很好的动态方法来解析 .WAV?也许如果我从“/”开始并解析到“?”

编辑:

预期输出如下:

19001.WAV
19307.WAV
19002.WAV

或者:

101.WAV
101.WAV
103.WAV

【问题讨论】:

  • 什么意思,显示预期的输出。可能只是做grep -o '/.*WAV'
  • 我进行了编辑以显示预期的输出。我已经尝试了一些其他的东西,但为此我得到了输出文件路径的其余部分。这会给我预期的输出,但显然不适用于 .WAV 的不同数量的字符:grep -o '[0-9][0-9][0-9][0-9][0-9][^"].WAV'
  • 这些程序的全部目的是解析动态字符串。所以是的,当然有可能。
  • 使用 GNU grep-o 选项,grep -o '[^/]*\.WAV' 应该可以完成这项工作。查找一系列零个或多个非斜杠,后跟.WAV。或grep -E -o '[^/]+\.WAV'。等等。
  • 这就是我要找的东西——我觉得自己无法得出这个结论是愚蠢的。感谢@JonathanLeffler 的帮助

标签: bash awk sed grep


【解决方案1】:
awk -F/ '{print substr($5,1,7)}' file

101.WAV
102.WAV
103.WAV

【讨论】:

    【解决方案2】:

    您列出的所有程序都使用正则表达式来解析名称,因此我将向您展示一个使用 grep 的示例,这可能是本案例中最基本的示例。

    有几个选项,具体取决于您在“.wav”之前定义 XXX 部分的确切方式。

    选项 1,正如您所指出的,只是文件名,即最后一个斜杠之后的所有内容:

    grep -hoi "[^/]\+\.WAV"
    

    这读作“斜线以外的任何字符”([^/]) 至少重复一次 (\+),后跟文字 .WAV (\.WAV)。

    选项 2 是只抓取扩展名之前的数字:

    grep -hoi "[[:digit:]]\+\.WAV"
    

    grep -hoi "[0-9]\+\.WAV"
    

    这些读作“数字”([[:digit:]][0-9] 表示相同的意思)至少重复一次 (\+),然后是文字 .WAV (\.WAV)。

    在所有情况下,我建议使用标志-h-o-i,我已将它们连接成一个选项-hoi-h 禁止输出中的文件名。 -o 使grep 只输出匹配的部分。 -i 使匹配不区分大小写,因此如果您的扩展名更改为 .wav 而不是 .WAV,您会没事的。

    此外,在所有情况下,输入都取决于您。你可以从另一个程序中输入它,看起来像

    program | grep -hoi "[^/]\+\.WAV"
    

    您可以使用标准输入重定向从文件中获取它:

    grep -hoi "[^/]\+\.WAV" < somefile.txt
    

    或者您可以将文件名传递给grep

    grep -hoi "[^/]\+\.WAV" somefile.txt
    

    【讨论】:

      【解决方案3】:

      试试这个 -

      awk  -F'[{":}/]' '{print $(NF-2)}' f
      19001.WAV
      19307.WAV
      19002.WAV
      

      egrep -o '[[:digit:]]{5}.WAV' f
      19001.WAV
      19307.WAV
      19002.WAV
      

      egrep -o '[[:digit:]]{5}.[[:alpha:]]{3}' f
      19001.WAV
      19307.WAV
      19002.WAV
      

      您可以根据需要在 egrep 中轻松更改数字和字符的值,但 awk 在这两种情况下都可以正常工作。

      【讨论】:

        【解决方案4】:

        只需按照 cmets 中的建议使用 grep

        grep -o '[^/]\{1,\}\.WAV' yourfile
        

        如果 wav 文件总是包含数字,这似乎更明确(结果相同):

        grep -o '[0-9]\{1,\}\.WAV'
        

        【讨论】:

          【解决方案5】:

          另一个awk

          awk -F'[/"]' '{print $(NF-1)}' file
          
          19001.WAV
          19307.WAV
          19002.WAV
          

          【讨论】:

          • 我考虑过使用[/"] 分隔符,但没想到从末尾倒数。 +1。不过,您可能需要一个选择器;如果输入确实是 JSON,那么也会打印 [] 行。
          【解决方案6】:

          假设文件的开头和结尾有 [] 行,看起来您的输入是 JSON,在这种情况下,我建议安装和使用 jq 而不是基于文本的实用程序,并做这样的事情:

          jq -r '.[]|.filename|split("/")[-1]' 
          

          但如果做不到这一点,列出的任何工具都可以正常工作。

          grep -o '[^/]*\.WAV'
          

          sed -ne 's,.*/\([^/]*\.WAV\).*$,\1,p' 
          

          awk -F'"' '/WAV/ {split($4,a,"/"); print a[length(a)]}'
          

          在每种情况下,还有多种其他可能的解决方案。

          【讨论】:

          • 我去的第一个方向是 jq 但由于我需要将此输出用于特定 Web 应用程序的方式,它不能使用 jq qithout 的输出再次对其进行正确格式化。其他选项只需通过一次即可正确格式化输出,因此我将使用它们。
          • 不确定我是否理解;上面jq 命令的输出看起来就像grepsedawk 命令的输出一样。没有额外的标点符号或任何东西。但不管怎样都行!
          • 你是对的——我很抱歉。我在想太多之前就回答了。我实现的jq 有这个问题,但你的解决方案也可以解决这个问题。
          【解决方案7】:

          或者用 sed

          $ sed 's,.*/,,; s,".*,,' x
          101.WAV
          102.WAV
          103.WAV
          

          解释:

          • s,.*/,, - 删除最右边的所有内容,包括最右边的 /
          • s,".*,, - 删除从最左边的 " 开始到行尾的所有内容

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2020-08-24
            • 2020-09-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-05-28
            • 2022-01-03
            相关资源
            最近更新 更多