【问题标题】:Read a single word from a string and set as a variable value in bash从字符串中读取单个单词并在 bash 中设置为变量值
【发布时间】:2016-06-29 04:40:20
【问题描述】:

我需要一个简单的函数来执行以下操作:

#!/bin/bash

select_word() {

echo "Enter a string."
read STRING

## User enters "This is a string."

## Here will be the command to set each word to the below variables.

WORD_1=
WORD_2=
WORD_3=
WORD_4=

echo -e "Word 1 is: $WORD_1.\n Word 2 is: $WORD_2.\n"
echo -e "Word 3 is: $WORD_3.\n Word 4 is: $WORD_4.\n"
}

我希望避免使用 sed 或 awk 等外部工具。寻找要使用的 bash 内置函数,以便从字符串中提取每个单词并将该单词设置为变量值。稍后我将使用“wc”来计算每个单词中的字符数。我已经知道怎么做,我只需要知道从用户输入字符串中提取单词的 bash 方法。

如果这个问题是重复的,我很抱歉,因为我找不到这个特定的问题。

【问题讨论】:

  • 您需要将这些词放在WORD_n 变量中吗?
  • 是的。如果用户输入是“这是一个字符串”。然后我需要这种格式的 WORD_1="This" WORD_2="is" WORD_3="a" WORD_4="string" 。这对于脚本的其余部分至关重要,它将使用每个单词的字符数来执行特定的功能。

标签: bash shell


【解决方案1】:

read 可以自己拆分字符串。

read -r WORD1 WORD2 WORD3 WORD4

如果您输入的字数少于 4 个,最后一个变量将被设置为空字符串。如果您输入 更多 个单词,WORD4 将是字符串的其余部分,而不仅仅是第 4 个单词。

如果不知道会提前输入多少字,也可以将字符串拆分成数组。

read -a words
WORD1=${words[0]}
WORD2=${words[1]}
WORD3=${words[2]}
WORD4=${words[3]}

【讨论】:

  • 这与我在您回答之前的编码非常接近。我将字符串拆分为变量“值”,在我有空变量之前,我执行字符串字数计数以查看字符串中有多少字,我使用该数字来设置我需要在数组中创建多少个值.所以它完全符合我的意图。用户输入的字符串可以是从几个词到整个段落的任何地方。所以我认为是理想的。
【解决方案2】:

可以将$STRING分隔的空格转换成数组,然后在$WORD_n变量中引用每个数组元素:

   WORDS=($STRING)

   WORD_1=${WORDS[0]}
   WORD_2=${WORDS[1]}

Of with set -f,这将禁用 globing(例如,将 * 更改为当前目录中的文件列表):

   set -f
   WORDS=($STRING)
   set +f

   WORD_1=${WORDS[0]}
   WORD_2=${WORDS[1]}

【讨论】:

  • 这会忽略字符串中每个单词之间的空格吗?
  • @YokaiSeishinkage 是的,它在空格上分割字符串
  • 这也让$STRING 进行全局扩展。
  • 这绝对不是正确的方法。请参阅 chepner 的答案,了解实现这一目标的正确方法。
  • @gniourf_gniourf 实际上 krzyk 的 最初的建议,在他编辑之前,正是我想要的。在我的系统上,它比使用 set -f 方法运行得更快。
【解决方案3】:

如果你需要独立于输入的字数,你可以这样做:

#!/bin/bash

select_word() {

echo "Enter a string."
read STRING

## User enters "This is a string."

GENERAL_VAR_NAME="WORD_"

## Here will be the command to set each word to the below variables.
# Split string into an array, default delimiter whitespace
STRING=( $STRING )

# Number of array elements: ${#STRING[@]}
for (( c=1; c<=${#STRING[@]}; c++ ))
do
        #echo -e "WORD $c is: ${STRING[$c]}"
        NEW_WORD=`echo -e $GENERAL_VAR_NAME${c}`
        printf -v $NEW_WORD "${STRING[$c]}"
done

# Check the output
for (( i=1; i<=${#STRING[@]}; i++ )); do
        echo "WORD_$i is $WORD_$i"
done

}

select_word

【讨论】:

  • 你的数组逻辑是正确的,我猜你是因为 GENERAL_VAR_NAME="WORD_" 的创造力而受到打击,或者缺乏清晰的重复使用 STRING 作为数组而没有先取消设置。 (有时你永远不知道为什么会发生拒绝投票,如果这样做的孩子缺乏诚信来停止并留下与他们的行为相关的评论。为了在array=( $STRING ) 之后表达你的观点,你可以简单地证明分词发生在单独的元素中使用declare -p array 删除数组并删除其余代码。然后这一点就很清楚了。
猜你喜欢
  • 1970-01-01
  • 2014-01-25
  • 1970-01-01
  • 2022-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-20
  • 2022-01-09
相关资源
最近更新 更多