【问题标题】:How to use variable with or operator | in awk如何将变量与 or 运算符一起使用 |在 awk
【发布时间】:2022-11-17 03:05:14
【问题描述】:

以下作品:

awk '
    NR==FNR { sub(/\.(png|txt|jpg|json)$/,""); a[$0]; next }
            { f=$0; sub(/\.(png|txt|jpg|json)$/,"", f) }
    !(f in a)
' comp1.txt comp2.txt > result.txt

现在我想让它把比较中应该忽略的文件结尾作为一个变量,但不能让它工作。我下面的尝试只是在不忽略任何文件结尾的情况下进行比较。我尝试使用 $ 和不使用,使用 () 和不使用,转义 |,但到目前为止没有成功。什么是正确的解决方案?

fileEndingsToIgnore="png|txt|jpg|json" 
awk -v fileEndingsToIgnore="${fileEndingsToIgnore}" '
    NR==FNR { sub(/\.(fileEndingsToIgnore)$/,""); a[$0]; next }
            { f=$0; sub(/\.(fileEndingsToIgnore)$/,"", f) }
    !(f in a)
' comp1.txt comp2.txt > result.txt

【问题讨论】:

    标签: awk


    【解决方案1】:

    GNU AWK 不允许你使用变量里面正则表达式文字,您可以将字符串变量与 ~!~ 以及许多 String functions 一起使用,但是在这种情况下,您需要按照 Using Dynamic Regexps 中的说明进行双重转义。考虑以下示例,假设您只想输出不带扩展名的 .txt.json 文件名,并且您有 file.txt 内容如下

    file1.txt
    file2.bmp
    file3.json
    

    然后

    awk 'BEGIN{s="\.(txt|json)$"}sub(s,""){print}' file.txt
    

    给出输出

    file1
    file3
    

    观察 \ 而不是

    (在 GNU Awk 5.0.1 中测试)

    【讨论】:

    • 感谢您的答复。您的示例不使用任何变量,我的示例也不使用,但我的示例通过单次转义成功运行。我只需要它来使用变量。所以我不明白你的例子与我的问题有什么关系,也许你可以澄清一下。
    【解决方案2】:

    一种解决方法是动态构建正则表达式并将其存储在变量中,然后在 sub() 调用中使用该变量。

    示例输入文件:

    $ cat test.file
    abc.txt
    def.jpg
    ghi.exe
    jkl.dat
    123.json
    456.ini
    789.pngX
    000.png
    111.dat
    

    一个awk想法:

    fileEndingsToIgnore="png|txt|jpg|json"
    
    awk -v fileEndingsToIgnore="${fileEndingsToIgnore}" '
    BEGIN { regex="\.(" fileEndingsToIgnore ")$" }         # need to escape the escape char, ie, "\"
          { out=$1
            sub(regex,"",out)
            printf "%s => %s
    ",$0,out
          }
    ' test.file
    

    这会产生:

    abc.txt => abc
    def.jpg => def
    ghi.exe => ghi.exe
    jkl.dat => jkl.dat
    123.json => 123
    456.ini => 456.ini
    789.pngX => 789.pngX
    000.png => 000
    111.dat => 111.dat
    

    将此应用于 OP 的当前代码:

    fileEndingsToIgnore="png|txt|jpg|json" 
    
    awk -v fileEndingsToIgnore="${fileEndingsToIgnore}" '
        BEGIN   { regex="\.(" fileEndingsToIgnore ")$" }
        NR==FNR { sub(regex,""); a[$0]; next }
                { f=$0; sub(regex,"", f) }
        !(f in a)
    ' comp1.txt comp2.txt > result.txt
    

    【讨论】:

    • 非常感谢,我不知道这样的解决方法是可能的,这解决了我的问题。
    【解决方案3】:

    我认为这应该足够通用:

    "-v FS=..." 是要排除的文件扩展名列表,区分大小写:

     mawk -v FS='mp[34]|txt|sh|awk' 'BEGIN { _^= FS = "[.]("FS")$" 
    
                    split("",__) } FNR==NR ? __[$_] : NF<=($_ in __)' file file
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-16
      • 2014-08-21
      • 2017-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多