从输出中切出不同的单词

从输出中切出不同的单词

假设,在linux shell中执行命令的结果如下:

X and Y are friends

有什么方法可以对结果中的每个单词(X、and、Y、are、friends)或前 n 个单词进行切片,以便它们可以用于不同的操作?

答案1

怎么样cut

$ phrase="X and Y are friends"
$ cut -d " " -f 1 <<< $phrase
X
$ cut -d " " -f 2 <<< $phrase
and
$ cut -d " " -f 3 <<< $phrase
Y
$ cut -d " " -f 4 <<< $phrase
are
$ cut -d " " -f 5 <<< $phrase
friends

指定-d分隔符(空格)和-f字段编号(由分隔符分隔的字段)。

在上面的示例中,我已将字符串放置在变量中,但您可以从命令的输出进行管道传输:

$ mycommand | cut -d " " -f 2
and    

答案2

您还可以使用以下命令直接在 shell 中进行此操作read

$ echo "X and Y are friends" | 
  while read a b c d e f
     do echo "a is '$a', b is '$b', c is '$c', d is '$d', e is '$e', f is '$f'"
  done
a is 'X', b is 'and', c is 'Y', d is 'are', e is 'friends', f is ''

默认分隔符是空格,但您可以通过更改变量将其设置为其他内容IFS

$ echo "foo:bar" | while IFS=: read  a b; do echo "a is '$a', b is '$b'"; done
a is 'foo', b is 'bar'

答案3

在 shell 脚本中捕获命令的输出有两种主要方法:命令替换read内置。

将输出拆分为单词的简单方法是依靠 shell 内置的拆分功能,并将输出放入数组中:

words=($(echo "X and Y are friends"))
echo "The ${words[5]} are ${words[1]} and ${words[3]}"

这适用于带有数组的 shell:ksh931、mksh、bash、zsh。在其他 shell 中,除了位置参数之外,您无法存储单词列表。

set -- $(echo "X and Y are friends")
echo "The $5 are $1 and $3"

实际上,输出中的每个单词都被视为通配符模式,并由匹配文件列表(如果有)替换。 (除了在 zsh 中,除非在 sh 兼容模式下,否则只有在明确指示时才执行此操作。)例如,如果其中一个单词是*,它将被当前目录中的文件列表替换。为了避免这种情况,请关闭通配符匹配:

set -f
words=($(echo "* and / are punctuation"))
echo "Here's some ${words[5]}: ${words[1]} and ${words[3]}"
set +f

使用read,您可以将各个单词分配给每个变量。棘手的部分read是,由于它从标准输入读取,因此通常用作管道中的右侧;但在大多数 shell 中(ATT ksh 和 zsh 除外),管道的两侧都在子 shell 中运行,因此变量分配会在管道外部丢失。您可以将其read作为指令序列的一部分。

echo "X and Y are friends" | {
  read -r first conjunction second verb complement remainder
  echo "The $complement are $first and $second"
}

或者,在 ksh93、bash 或 zsh 中,您可以将输入传递到流程替代

read -r first conjunction second verb complement remainder <(echo "X and Y are friends")
echo "The $complement are $first and $second"

如果你想将单词存储在数组中,你可以read -rA words在 mksh、ksh93 和 zsh 中使用,或者read -ra words在 bash 中使用,例如在 bash 中

read -ra words <(echo "X and Y are friends")

相当于

set -f; words=$((echo "X and Y are friends")); set +f

如果该命令输出一行,但-f如果该选项之前已打开,则它不会重置该选项。

¹ Ksh88 有数组,但赋值使用不同的语法。

答案4

zsh

upToFirst5words=(${$(my-cmd)[1,5]})

假设默认值是 IFS 的默认值,它将按序列空白(空格、制表符、换行符)或 NUL 进行拆分。

你可以做到:

argv=(${$(my-cmd)[1,5]})

对于这 5个词$1$2...。$5

相关内容