【问题标题】:AWK - how to improve this exampleAWK - 如何改进这个例子
【发布时间】:2023-04-06 03:12:01
【问题描述】:

目录内容:

$ ls | awk '1'
ala
cztery.AVI
dwa.AvI
Jeden.aVI
lupa.com
PIĘĆ.AVI
trzy.Avi
zero.avi

此命令打印:

$ ls | awk '$0=tolower($0){a=substr($0,1,length($0)-4)}{if(/avi$/){system("echo "$0" "a"\".mpg\"")}}'
cztery.avi cztery.mpg
dwa.avi dwa.mpg
jeden.avi jeden.mpg
pięć.avi pięć.mpg
trzy.avi trzy.mpg
zero.avi zero.mpg

如何改进上述命令?我要打印:

cztery.avi cztery.mpg
dwa.avi dwa.mpg
jeden.avi Jeden.mpg
pięć.avi PIĘĆ.mpg
trzy.avi trzy.mpg
zero.avi zero.mpg

【问题讨论】:

    标签: awk


    【解决方案1】:

    一种方式:

    ls  *[aA][vV][iI] | awk '{print tolower($0) " " substr($0,0,length($0)-3)"mpg";}'
    

    【讨论】:

    • 第2列的文件名应该保留原来的大小写。
    • " " 可以简单地变成,awk的默认OFS是一个空格。
    • 如果您的目录中有一个名为“peccavi”的文件,则发布的 ls 命令将失败,因为它缺少一个“.”
    • 请awk解决,里面使用system()。由于系统将用于启动另一个 bash 命令。
    【解决方案2】:

    如何使用 find first 来匹配所有 avi 文件:

    $ find -iname "*.avi" -exec basename {} \; | awk -F. '{print tolower($1) ".avi", $1 ".mpg"}'
    cztery.avi cztery.mpg
    dwa.avi dwa.mpg
    jeden.avi Jeden.mpg
    pięć.avi PIĘĆ.mpg
    trzy.avi trzy.mpg
    zero.avi zero.mpg
    
    $ ls -1 # Use the -1 option of ls instead of ls | awk '1'
    ala
    cztery.AVI
    dwa.AvI
    Jeden.aVI
    lupa.com
    PIĘĆ.AVI
    trzy.Avi
    zero.avi
    

    如果您正在寻找最短的解决方案,请使用Guruls 和我的awk

    ls *.[aA][vV][iI] | awk -F. '{print tolower($1)".avi",$1".mpg"}'
    cztery.avi cztery.mpg
    dwa.avi dwa.mpg
    jeden.avi Jeden.mpg
    pięć.avi PIĘĆ.mpg
    trzy.avi trzy.mpg
    zero.avi zero.mpg
    

    【讨论】:

    • 感谢您提供好的解决方案。如果可能,请纠正我的例子。
    • 如果文件名包含多个文字 . 会发生什么?
    • @steve 这是一个奖金回合:P awk 'BEGIN{FS=OFS="."}{$NF=""; NF--; print tolower($0),"avi "$0,"mpg"}'
    • @steve 是对的,不过,文件名中有多个“.”是很常见的情况。此外,如果您的目录中有一个名为“peccavi”的文件,则发布的ls 命令将失败,因为它缺少“.”。
    • 请awk解决,里面使用system()。由于系统将用于启动另一个 bash 命令。
    【解决方案3】:
    ls | awk '{lc=tolower($0)} lc~/\.avi$/{sub(/...$/,"mpg"); print lc,$0}'
    

    请注意,这不适用于包含换行符的文件名。如果您有这种情况,请告诉我们。

    你在下面的 cmets 中说:

    我想让系统运行这个命令->

    ls | awk '{a=substr($0,1,length($0)-4)}/avi$|AVI$/{system("ffmpeg -i "$0" -f avi -vcodec libxvid "a"\".mpg\"")}'
    

    正如我所提到的,这只是没有以正确的方式思考。为了明确起见,您正在这样做:

    shell ( ls | awk ( system( shell ( ffmpeg ) ) ) )
    

    这不是更有意义吗:

    shell ( ls | awk; ffmpeg )
    

    我实际上完全不明白您为什么要为此使用 awk,因为这一切都是在 shell 中完成的,但是假设您有自己的理由,这里是实现您发布的内容的正确方法:

    ls *.avi *.AVI |
    awk '{print $0, substr($0,1,length($0)-3) "\"mpg\""}' |
    while read -r orig mpeg
    do
        ffmpeg -i "$orig" -f avi -vcodec libxvid "$mpeg"
    done
    

    请注意,如果您的文件名中有空格,这将失败,但如果这是更好的解决方案,那么修复它是没有意义的:

    ls *.avi *.AVI |
    while IFS= read -r orig
    do
        ffmpeg -i "$orig" -f avi -vcodec libxvid "${orig%avi}mpeg"
    done
    

    请注意,您最初将文件名转换为小写的要求在您说要实施的解决方案中消失了。

    另外,请注意,由于此解决方案基于您所说的要实施的内容,因此不适用于您最初发布的文件列表,因为它仅适用于以 .avi 或 .AVI 结尾的文件,而不适用于 .Avi . ls *.[Aa][Vv][Ii] 会在必要时解决这个问题。

    【讨论】:

    • 请awk解决,里面使用system()。由于系统将用于启动另一个 bash 命令。
    • 没有。您需要停止尝试使用 system() ,因为它几乎总是错误的方法。如果您更新您的问题以告诉我们您正在尝试做什么,我们可以提供正确的解决方案,并且几乎可以肯定它不会涉及调用 system()。
    • 我想让系统运行这个命令 -> ls | awk '{a=substr($0,1,length($0)-4)}/avi$|AVI$/{system("ffmpeg -i "$0" -f avi -vcodec libxvid "a"\".mpg\"")}'
    • 不,你没有。您想编写一个脚本来完成某个目标。您认为使用 system() 是实现该脚本的正确方法。它不是。我会用正确的方法更新我的答案,假设你还没有告诉我们其他任何事情。
    • @EdMorton,感谢您对更好解决方案的解释和介绍。
    【解决方案4】:

    这是我使用GNU awk 的方法:

    for i in *.[Aa][Vv][Ii]; do echo "$(echo $i | awk '{ print tolower($0), gensub(/...$/,"mpg","") }')"; done
    

    结果:

    cztery.avi cztery.mpg
    dwa.avi dwa.mpg
    jeden.avi Jeden.mpg
    pięć.avi PIĘĆ.mpg
    trzy.avi trzy.mpg
    zero.avi zero.mpg
    

    【讨论】:

    • 如果 $i 包含通配符等,那将失败。总是引用你的变量。也不确定环绕回声的意义是什么,在这种情况下,没有必要强迫它使用 gensub() 进行 gawk-sepcific。
    • 请awk解决,里面使用system()。由于系统将用于启动另一个 bash 命令。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-02
    • 2014-08-12
    • 1970-01-01
    • 2011-10-16
    • 2015-07-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多