假设我有以下字符串:x="number 1;number 2;number 3"
。
通过 ${x%%";"*}
成功访问第一个子字符串,通过以下方式成功访问最后子字符串${x##*";"}
:
$ x="number 1;number 2;number 3"
$ echo "front : ${x%%";"*}" #front-most-part
number 1
$ echo "back : ${x##*";"}" #back-most-part
number 3
$
如何访问中间部分:(例如数字2
)?
如果我有(很多...)更多零件而不是三个,是否有更好的方法来做到这一点?
换句话说:是否有一种通用的方法来访问字符串 yyy
的子字符串 n
,由字符串 xxx
分隔,其中 xxx
是任意字符串/分隔符?
我已阅读How do I split a string on a delimiter in Bash? ,但我特别不想迭代字符串,而是直接访问给定的子字符串。
这具体不要求或分割成数组,而是分割成子字符串。
最佳答案
具有固定索引:
x="number 1;number 2;number 3"
# Split input into fields by ';' and read the 2nd field into $f2
# Note the need for the *2nd* `unused`, otherwise f2 would
# receive the 2nd field *plus the remainder of the line*.
IFS=';' read -r unused f2 unused <<<"$x"
echo "$f2"
一般来说,使用数组:
x="number 1;number 2;number 3"
# Split input int fields by ';' and read all resulting fields
# into an *array* (-a).
IFS=';' read -r -a fields <<<"$x"
# Access the desired field.
ndx=1
echo "${fields[ndx]}"
约束:
使用IFS
,指定I内部F字段S分隔符字符的特殊变量,总是表示:
只有单个文字字符可以充当字段分隔符。
- 但是,您可以指定多个 个字符,在这种情况下,其中任何 个字符都将被视为分隔符。
默认分隔符为
$' \t\n'
- 即,空格、制表符和换行符以及它们的运行(多个连续实例)始终被视为单个分隔符;例如,'a b'
有 2 个字段 - 多个空格算作单个分隔符。相比之下,与任何其他字符相比,连续中的字符被单独考虑,因此单独的空字段;例如,
'a;;b'
有 3 个字段 - 每个;
是它自己的分隔符,因此;;
之间有一个空字段.
read -r -a ... <<<...
技术通常效果很好,只要:
- 输入是单行
- 您不担心尾随空字段被丢弃
如果您需要一个完全通用、强大的解决方案来解决上述问题, 使用以下变体,这在@gniourf_gniourf answer here中进行了解释:
sep=';'
IFS="$sep" read -r -d '' -a fields < <(printf "%s${sep}\0" "$x")
注意需要使用-d ''
一次读取多行输入,并且需要使用另一个分隔符实例终止输入以保留尾随空字段;尾随 \0
需要确保 read
的退出代码是 0
.
关于string - bash 4 : Generic access to substring (n) of string by arbitrary delimiter?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33368514/