数组上的 Bash 子串扩展
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20160838/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Bash substring expansion on array
提问by H?kon H?gland
I have a set of files with a given suffix. For instance, I have a set of pdf files with suffix .pdf
. I would like to obtain the names of the files without the suffix using substring expansion.
我有一组带有给定后缀的文件。例如,我有一组后缀为 .pdf 的 pdf 文件.pdf
。我想使用子字符串扩展获取没有后缀的文件名。
For a single file I can use:
对于单个文件,我可以使用:
file="test.pdf"
echo ${file:0 -4}
To do this operation for all files, I now tried:
要对所有文件执行此操作,我现在尝试:
files=( $(ls *.pdf) )
ff=( "${files[@]:0: -4}" )
echo ${ff[@]}
I now get an error saying that substring expression < 0
..
我现在收到一个错误说substring expression < 0
..
( I would like to avoid using a for
loop )
(我想避免使用for
循环)
回答by gniourf_gniourf
Use parameter expansionsto remove the .pdf
part like so:
使用参数扩展来删除.pdf
部分,如下所示:
shopt -s nullglob
files=( *.pdf )
echo "${files[@]%.pdf}"
The shopt -s nullglob
is always a good idea when using globs: it will make the glob expand to nothing if there are no matches.
在shopt -s nullglob
使用时,水珠总是一个好主意:它将使水珠扩大到什么,如果没有匹配。
"${files[@]%.pdf}"
will expand to an array with all the trailing .pdf
removed. You can, if you wish put this in another array as so:
"${files[@]%.pdf}"
将扩展为.pdf
删除所有尾随的数组。你可以,如果你想把它放在另一个数组中:
files_noext=( "${files[@]%.pdf}" )
All this is 100% safe regarding funny symbols in filenames (spaces, newlines, etc.), except for the echo
part for files named -n.pdf
, -e.pdf
and -E.pdf
... but the echo
was just here for demonstration purposes. Your files=( $(ls *.pdf) )
is really really bad! Do never parse the output of ls
.
对于文件名中的有趣符号(空格、换行符等),所有这些都是 100% 安全的,除了echo
名为-n.pdf
,-e.pdf
和-E.pdf
... 的文件部分,但echo
这里只是为了演示目的。你files=( $(ls *.pdf) )
真的很糟糕!永远不要解析ls
.
To answer your comment: substring expansions don't work on each field of the array. Taken from the reference manual linked above:
回答您的评论:子字符串扩展不适用于数组的每个字段。取自上面链接的参考手册:
${parameter:offset}
${parameter:offset:length}
If
offset
evaluates to a number less than zero, the value is used as an offset from the end of the value ofparameter
. Iflength
evaluates to a number less than zero, andparameter
is not@
and not an indexed or associative array, it is interpreted as an offset from the end of the value ofparameter
rather than a number of characters, and the expansion is the characters between the two offsets. Ifparameter
is@
, the result islength
positional parameters beginning at offset. Ifparameter
is an indexed array name subscripted by@
or*
, the result is thelength
members of the array beginning with${parameter[offset]}
.A negative offset is taken relative to one greater than the maximum index of the specified array. Substring expansion applied to an associative array produces undefined results.
${parameter:offset}
${parameter:offset:length}
如果
offset
计算结果为小于零的数字,则该值用作距 的值末尾的偏移量parameter
。如果length
计算结果为小于零的数字,并且parameter
不是@
索引或关联数组,则将其解释为距值末尾的偏移量parameter
而不是多个字符,并且扩展是两个偏移量之间的字符. 如果parameter
是@
,则结果是length
从偏移量开始的位置参数。如果parameter
是一个以@
或为下标的索引数组名称*
,则结果为以length
开头的数组成员${parameter[offset]}
。相对于大于指定数组的最大索引的一个负偏移量。应用于关联数组的子字符串扩展会产生未定义的结果。
So, e.g.,
所以,例如,
$ array=( zero one two three four five six seven eight )
$ echo "${array[@]:3:2}"
three four
$