bash 4:通过任意分隔符通用访问字符串的子字符串 (n)?
bash 4: Generic access to substring (n) of string by arbitrary delimiter?
假设我有以下字符串:x="number 1;number 2;number 3"
.
通过 ${x%%";"*}
成功访问 first 子字符串,通过 [=14= 访问 last 子字符串]:
$ x="number 1;number 2;number 3"
$ echo "front : ${x%%";"*}" #front-most-part
number 1
$ echo "back : ${x##*";"}" #back-most-part
number 3
$
如何访问中间部分:(例如number 2
)?
如果我有(很多...)更多的部分然后只有三个,有没有更好的方法来做到这一点?
换句话说:是否有一种通用的方法来访问字符串yyy
[=42=的第n
号子串], 由字符串分隔 xxx
其中 xxx
是一个任意值 string/delimiter?
我已阅读 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'
——即space、制表符和换行符,以及 运行s 其中(多个连续实例)始终被视为 单个 分隔符;例如,'a b'
有 2 个字段 - 多个 space 算作一个分隔符。
相比之下,与任何其他字符,一个运行中的字符被单独考虑,因此分隔空 字段;例如,'a;;b'
有 3 个字段 - 每个 ;
都是它自己的分隔符,因此 ;;
.
[ 之间有一个空字段=82=]
read -r -a ... <<<...
技术 通常效果很好,只要 :
- 输入是单行
- 您不担心 尾随的空白字段被丢弃
如果您需要一个完全通用、强大的解决方案来解决上述问题,
使用以下变体,在 @gniourf_gniourf answer here:
中进行了解释
sep=';'
IFS="$sep" read -r -d '' -a fields < <(printf "%s${sep}[=12=]" "$x")
注意需要使用 -d ''
一次读取多行输入,并且需要用另一个分隔符实例终止输入以保留尾随的空字段;需要尾随 [=21=]
以确保 read
的退出代码是 0
.
不要使用:
创建一个数组,分隔符为;
:
x="number 1;number 2;number 3"
_IFS=$IFS; IFS=';'
arr=($x)
IFS=$_IFS
echo ${arr[0]} # number 1
echo ${arr[1]} # number 2
echo ${arr[2]} # number 3
假设我有以下字符串:x="number 1;number 2;number 3"
.
通过 ${x%%";"*}
成功访问 first 子字符串,通过 [=14= 访问 last 子字符串]:
$ x="number 1;number 2;number 3"
$ echo "front : ${x%%";"*}" #front-most-part
number 1
$ echo "back : ${x##*";"}" #back-most-part
number 3
$
如何访问中间部分:(例如number 2
)?
如果我有(很多...)更多的部分然后只有三个,有没有更好的方法来做到这一点?
换句话说:是否有一种通用的方法来访问字符串yyy
[=42=的第n
号子串], 由字符串分隔 xxx
其中 xxx
是一个任意值 string/delimiter?
我已阅读 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'
——即space、制表符和换行符,以及 运行s 其中(多个连续实例)始终被视为 单个 分隔符;例如,'a b'
有 2 个字段 - 多个 space 算作一个分隔符。相比之下,与任何其他字符,一个运行中的字符被单独考虑,因此分隔空 字段;例如,
[ 之间有一个空字段=82=]'a;;b'
有 3 个字段 - 每个;
都是它自己的分隔符,因此;;
.
read -r -a ... <<<...
技术 通常效果很好,只要 :
- 输入是单行
- 您不担心 尾随的空白字段被丢弃
如果您需要一个完全通用、强大的解决方案来解决上述问题, 使用以下变体,在 @gniourf_gniourf answer here:
中进行了解释sep=';'
IFS="$sep" read -r -d '' -a fields < <(printf "%s${sep}[=12=]" "$x")
注意需要使用 -d ''
一次读取多行输入,并且需要用另一个分隔符实例终止输入以保留尾随的空字段;需要尾随 [=21=]
以确保 read
的退出代码是 0
.
不要使用:
创建一个数组,分隔符为;
:
x="number 1;number 2;number 3"
_IFS=$IFS; IFS=';'
arr=($x)
IFS=$_IFS
echo ${arr[0]} # number 1
echo ${arr[1]} # number 2
echo ${arr[2]} # number 3