如何解析 bash 中的多行命令输出?

如何解析 bash 中的多行命令输出?

我有一个输出以下内容的命令:

Some text here
    1,3456: "Descr 1"
    2,7891: "Descr 2"
    3,0976: "Descr 3"

Some other random text here

我想编写一个 bash 脚本来解析第一列并将值存储在某处,以便我可以向最终用户提供选项。

我可以使用 awk 获取第一列,但由于末尾的随机文本(“这里有其他一些随机文本”),它弄乱了我的 awk 命令。

这是我到目前为止所拥有的:

#!/bin/bash

VERSIONS=`/usr/libexec/somebin -V`

OPTIONS=$VERSIONS | awk -F'[,]' '{print $1}'

while read -r line; do
   echo "... $line ..."
done <<< $OPTIONS

它所做的就是打印出:

Some text here
    1,3456: "Descr 1"
    2,7891: "Descr 2"
    3,0976: "Descr 3"

...  ...

但我希望它打印出来:

1
2
3

答案1

管道之前的简单命令:

OPTIONS=$VERSIONS | awk -F'[,]' '{print $1}'

设置OPTIONS$VERSIONS.由于那里没有实际的实用程序名称,因此该命令只是一个赋值,因此它不会产生任何输出。因此没有任何内容通过管道传输到awk,因此awk什么也不做。 (即使它做了某事,它也不会这样做$OPTIONS

更糟糕的是,管道确保之前的命令和之后的命令都在子 shell 中执行。因此OPTIONS未在包含复合命令的 shell 中设置。

我想你想要的是这样的:

OPTIONS=$(/usr/libexec/somebin -V | cut -f1 -d,)

或者可能

VERSIONS=$(/usr/libexec/somebin -V)
OPTIONS=$(echo "$VERSIONS" | cut -f1 -d,)

其中该cut命令执行的操作与您调用awk.

但是,无论是它还是你的 awk 命令都不会过滤掉带有“某些文本”的行,所以也许你需要一个实际的过滤器,也许是这样的:

VERSIONS=$(/usr/libexec/somebin -V | grep ,)
OPTIONS=$(echo "$VERSIONS" | cut -f1 -d,)

答案2

awk -F'[,]' '/^[ ]/{print $1}'

只会作用于以空格开头的行,从而跳过那些没有空格的行。另一种选择可能是查找包含逗号的行,或者如果使用阴险的制表符而不是空格,则查找不同的正则表达式...

答案3

你可以单独使用 bash 来做到这一点——

IFS=","; while read -r a b; do [[ $a =~ [0-9]+ ]] && echo $a; done < 1; unset IFS
1
2
3

相关内容