数组上的 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 08:44:36  来源:igfitidea点击:

Bash substring expansion on array

arraysbashsubstrexpansion

提问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 forloop )

(我想避免使用for循环)

回答by gniourf_gniourf

Use parameter expansionsto remove the .pdfpart like so:

使用参数扩展来删除.pdf部分,如下所示:

shopt -s nullglob
files=( *.pdf )
echo "${files[@]%.pdf}"

The shopt -s nullglobis 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 .pdfremoved. 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 echopart for files named -n.pdf, -e.pdfand -E.pdf... but the echowas 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 offsetevaluates to a number less than zero, the value is used as an offset from the end of the value of parameter. If lengthevaluates to a number less than zero, and parameteris not @and not an indexed or associative array, it is interpreted as an offset from the end of the value of parameterrather than a number of characters, and the expansion is the characters between the two offsets. If parameteris @, the result is lengthpositional parameters beginning at offset. If parameteris an indexed array name subscripted by @or *, the result is the lengthmembers 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
$