【问题标题】:Get unevenly seperated fields from bash command从 bash 命令中获取不均匀分隔的字段
【发布时间】:2018-02-15 08:13:49
【问题描述】:

我正在编写一个脚本并想运行 bzip2,但只能获得压缩比、压缩大小和未压缩大小。

当我运行bzip2 filename 时,我得到:

test.txt: 5.769:1, 1.387 bits/byte, 82.67% saved, 48108 in, 8339 out.

我只想获取最后三个字段:

82.67% saved, 48108 in, 8339 out

我已经尝试使用 awk

bzip2 -v test.txt | awk '{print $1 $2 $3}' 以及

bzip2 -v test.txt | awk -F', ' '{print $1}'

但由于它是一个字符串并且分隔符的间距不均匀,我不知道该怎么做。我也想摆脱任何文本,只输出数字,像这样 82.67% 48108 8339

我必须尽可能简单。谢谢!

编辑:

bzip2 -v test.txt | cat -A 的输出:

test.txt:  0.788:1, 10.154 bits/byte, -26.92% saved, 52 in, 66 out.

脚本:

#!/bin/sh
# program2.sh 

#Name of the file input
NAME=$1

#Uncompressed size of the file input
UNCOMPRESSED=$(du -h $NAME | awk '{print $1}')



#################################################

#Prompts name entry if no argument provided, or stores given argument as name
if [ $# -eq 0 ];
  then
    echo "Error: No file name provided. Please run the script with a filename argument." 
    echo ""
    exit
fi

echo ""
echo "$NAME will be compressed using the gzip, bzip2, and zip commands."
echo ""
echo "gzip:"

#echoUncompressed:\t $UNCOMPRESSED"
gzip $NAME 
gzip -l  ${NAME%}.gz | awk ' NR == 2 {print "Uncompressed:\t " $2} NR == 2 {print "Compressed:\t " $1}   NR == 2 {print "Ratio:\t\t " $3}'
gunzip ${NAME%}.gz


echo ""
echo "bzip2:"
echo "Uncompressed:\t $UNCOMPRESSED"
#Run bzip2 
bzip2 -v $NAME |& awk -F ',[[:blank:]]*' '{sub(/\.$/, ""); printf "Ratio: %s, Uncompressed: %s, Compressed: %s\n", $(NF-2), $(NF-1), $NF}'
bunzip2 ${NAME%}.bz2


echo ""
echo "zip:"
#echoUncompressed:\t $UNCOMPRESSED"
#Run zip 
zip -q ${NAME%.*}.zip $NAME 
ZNAME="${NAME%.*}.zip"
unzip -ov $ZNAME | awk ' NR == 4 {print "Compressed:\t " $3}   NR == 4 {print "Ratio:\t\t "   $4}'

【问题讨论】:

    标签: bash awk bzip2


    【解决方案1】:

    你可以使用:

    bzip2 -v test.txt |& awk -F ',[[:blank:]]*' '{sub(/\.$/, "");
    printf "Ratio: %s, Uncompressed: %s, Compressed: %s\n", $(NF-2), $(NF-1), $NF}'
    

    Ratio: 82.67% saved, Uncompressed: 48108 in, Compressed: 8339 out
    

    这里-F ',[[:blank:]]*' 使逗号后跟0 个或多个空格作为awk 的输入字段分隔符。

    Working Script Demo

    【讨论】:

    • 它仍然输出完整的 -v 命令。 :( 什么是 OFS 以及为什么 -F 参数中的选项卡?
    • 检查更新的答案。似乎bzip2 -v 将输出写入stderr 而不是stdout 这就是为什么你需要|& 而不仅仅是|
    • @anubhava,谢谢 TON 先生,有一天我想像你一样知识渊博,怎么变成这样? :)
    • @RavinderSingh13:谢谢你的好话。你的答案已经越来越好了,很多时候我发现你的方法比我的更好。
    • @anubhava,先生,你真好,相信我,不管你信不信,我会花 1 小时阅读你的答案(因为它们本身就是知识的海洋),你总是在我的祈祷中当你帮助了很多人时,上帝保佑你,先生,你的摇滚 :)
    【解决方案2】:

    遵循简单的awk 可能会对您有所帮助:

    your command |& awk '{sub(/.*byte, +/,"");print}'
    

    根据 anubhava sir'e 的建议编辑 !& 现在也回答。

    bzip2 -v Input_file |& awk '{sub(/.*byte, +/,"");split($0,a," ");print "Ratio: ",a[1],",Uncompressed: ",a[2]," Compressed:",a[3]}'
    

    【讨论】:

    • 我仍然得到了 bzip2 -v 的完整输出
    • 有什么方法可以在字段之间添加文本?就像我对anubhava答案的评论一样?不过你的也很好用!
    • @jrdev,现在检查。
    • 对不起,这本身就有效,但在我的脚本中不起作用。我试图将命令放在脚本中,它说意外 &
    • 看看我的回答
    【解决方案3】:

    因此,当不使用脚本时,上述解决方案有效。但是在脚本中,从 stderr 到 stdout 的重定向是不同的:

    bzip2 -v $NAME 2>&1| awk -F ',[[:blank:]]*' '{sub(/\.$/, ""); printf "Ratio: %s, Uncompressed: %s, Compressed: %s\n", $(NF-2), $(NF-1), $NF}'
    

    使用2>&1 在脚本中重定向,在脚本之外您可以像在其他解决方案中一样使用command |& ...."

    【讨论】:

    • 请避免发布带有微小变化的脚本作为单独的答案。这与我建议的 awk 命令相同。
    猜你喜欢
    • 1970-01-01
    • 2019-01-03
    • 2016-10-10
    • 2018-04-26
    • 1970-01-01
    • 1970-01-01
    • 2012-08-26
    • 1970-01-01
    • 2021-01-14
    相关资源
    最近更新 更多