如何根据有空格的分隔符剪切字符串

如何根据有空格的分隔符剪切字符串
variable_list="
 any:any:-a -b -c any
 one:one:-c -b -f -m mul
 mul:one:-c -b -f -m mul
"
for f in `echo $variable_list`
do
  c1=`echo $f | cut -d':' -f1`;
  c2=`echo $f | cut -d':' -f2`;
  c3=`echo $f | cut -d':' -f3-`;
  echo "c1==>$c1 and c2==>$c2 and c3==>$c3";
  #exit 0; ###I made mistake here
done;

预期输出:

c1==>any and c2==>any and c3==>-a -b -c any
c1==>one and c2==>one and c3==>-c -b -f -m mul
c1==>mul and c2==>one and c3==>-c -b -f -m mul

编辑1:

我意识到我在使用脚本时很愚蠢,并且在第一次迭代时我exit 0只测试了它的第一行,因为我实际上有很多这样的脚本。它按照它必须的方式工作。

variable_list我可以通过维护而不修改输入的格式/方式来实现上述输出吗?

(我使用的是bash)

答案1

您的问题与数据中的空格有关。 shell 会将字符串拆分为所有空格上的单词,并且循环for将迭代这些单词。

(对于不替换variable_list为数组的解决方案,请参阅此答案的最后部分。)

相反,使用适当的数组:

variable_list=(
    "any:any:-a -b -c any"
    "one:one:-c -b -f -m mul"
    "mul:one:-c -b -f -m mul"
)

for var in "${variable_list[@]}"; do
    c1=$( cut -d':' -f1  <<<"$var" )
    c2=$( cut -d':' -f2  <<<"$var" )
    c3=$( cut -d':' -f3- <<<"$var" )
    printf 'c1==>%s and c2==>%s and c3==>%s\n' "$c1" "$c2" "$c3"
done

使用数组可确保您可以将每个单独的变量集作为其自己的数组条目进行访问,而无需依赖换行符或其他字符分隔它们。

该代码还使用“here-strings”将bash字符串发送到cut(而不是echo管道)。

或者,更有效地,

variable_list=(
    "any:any:-a -b -c any"
    "one:one:-c -b -f -m mul"
    "mul:one:-c -b -f -m mul"
)

for var in "${variable_list[@]}"; do
    IFS=':' read -r c1 c2 c3 <<<"$var"
    printf 'c1==>%s and c2==>%s and c3==>%s\n' "$c1" "$c2" "$c3"
done

设置IFS为冒号 forread将使read输入在冒号上分割(而不是在空格、制表符和换行符上)。

请注意,以上所有引用都很重要。如果没有双引号,shell 将对variable_listvar和三个c变量的值执行分词和文件名匹配。

有关的:


如果您所追求的只是特定的输出,那么您可能会作弊:

variable_list=(
    "any:any:-a -b -c any"
    "one:one:-c -b -f -m mul"
    "mul:one:-c -b -f -m mul"
)

( IFS=':'; set -f; printf 'c1==>%s and c2==>%s and c3==>%s\n' ${variable_list[@]} )

这会printf在子 shell 中运行,以便设置IFS-f( noglob) shell 选项不会影响脚本的其余部分。此处设置IFS冒号将使 shell 展开未引用的 variable_list数组分成三组,每组三个参数printfprintf将根据其格式字符串打印前三个参数,然后为下一组三个参数重用该格式,直到处理完所有参数。

如果其中存在任何文件名通配字符,则可以set -f防止未加引号的扩展触发文件名通配。variable_list


使用换行符分隔的字符串:

variable_list="
any:any:-a -b -c any
one:one:-c -b -f -m mul
mul:one:-c -b -f -m mul"

while IFS= read -r var; do
    IFS=':' read -r c1 c2 c3 <<<"$var"
    printf 'c1==>%s and c2==>%s and c3==>%s\n' "$c1" "$c2" "$c3"
done <<<"$variable_list"

这会从字符串中读取数据,就像它来自文件一样。

有关的:

答案2

您可以使用 awk 来获取输出:

echo "$variable_list" | awk -F: '
{
  sub("^ ","")
  for(i=1;i<=NF;i++)
    sub(/^/,"c" i "==>",$i)
}1' OFS=" and "

相关内容