将数组字段移动到另一个数组中的另一个字段进行编辑

时间:2013-11-10 14:17:18

标签: arrays bash directory

此脚本应将文件夹存储在fvar2中的目录中folder1/ folder2/ folder3/ 然后使用“sed”命令在fvar1中作为folder1 folder2 folder3回显。 最后它应该回应新数组fvar1

中的所有dirs

这是错误

./test.sh: line 18: syntax error near unexpected token ``echo "${fvar2[svar3]}" | sed 's#/##g'`'
./test.sh: line 18: `{fvar1[svar4]}=(`echo "${fvar2[svar3]}" | sed 's#/##g'`)'

这是脚本

#!/bin/bash

fvar2=(*/)
svar3=0
svar4=0

while true
do

{fvar1[svar4]}=(`echo "${fvar2[svar3]}" | sed 's#/##g'`)
svar3=`expr $svar3 + 1`
svar4=`expr $svar4 + 1`
echo "${fvar1[svar4]}"

done

1 个答案:

答案 0 :(得分:2)

正确的bash方式:

#!/bin/bash

# When using globs, always use either nullglob or failglob
shopt -s nullglob

# define your array fvar2
declare -a fvar2=( */ )

# Remove the trailing slash in each field of fvar2, and make an array fvar1 of it
declare -a fvar1=( "${fvar2[@]%/}" )

# Print each field of array fvar2, one field per line
printf '%s\n' "${fvar1[@]}"

对于带有趣符号(空格,换行符等)的文件名,这是100%安全和防弹。


现在让我稍微扩展一下这个答案,向您展示如何使用更复杂的处理从另一个构建数组。通常,可以使用Shell Parameter Expansions完成简单的处理。但是,如果这还不够,例如,您希望仅保留长度为4的子串,从数组array1中每个字段的偏移量7开始。解决方案

declare -a array2=( "${array1[@]:7:4}" )

将无效,因为这将占用array1的字段7到11,因为您将在我上面给出的链接中读到。在这里,您确实需要遍历array1,进行处理,然后在array2上推送。这就是你要做的:

# empty and initialize array2
declare -a array2=()
for i in "${array2[@]}"; do
    array2+=( "${i:7:4}" )
done

+=运算符将连接lhs和rhs的数组,将结果放在lhs的数组上。看:

$ declare -a array1=( banana{00..10}gorilla )
$ printf '%s\n' "${array2[@]}"
banana00gorilla
banana01gorilla
banana02gorilla
banana03gorilla
banana04gorilla
banana05gorilla
banana06gorilla
banana07gorilla
banana08gorilla
banana09gorilla
banana10gorilla
$ declare -a array2=()
$ for i in "${array1[@]}"; do array2+=( "${i:7:4}" ); done
$ printf '%s\n' "${array2[@]}"
0gor
1gor
2gor
3gor
4gor
5gor
6gor
7gor
8gor
9gor
0gor

请求解释shopt -s nullglob

当使用bash的globs时,总是使用shopt -s nullglobshopt -s failglob你真的想要一个健壮的脚本。为什么?看:

$ shopt -u nullglob failglob # unsetting nullglob and failglob
$ echo there_are_no_files_matching_this_glob_in_this_directory_*
there_are_no_files_matching_this_glob_in_this_directory_*

如您所见,当nullglob和failglob未设置时,如果没有globbing匹配,bash会将glob扩展为自身,逐字逐句。这可能会导致脚本内部出现可怕的内容,例如,如果您想通过将.txt添加到banana来重命名所有以.txt结尾的文件,那么您可以这样做...但是如果没有目录中以$ shopt -u nullglob failglob $ for i in *.txt; do mv "$i" "banana$i.txt"; done mv: cannot stat `*.txt': No such file or directory $ # oh dear :( 结尾的文件?

:(

是的,哦,亲爱的nullglob ,因为你在没有控制其参数的情况下运行命令......这可能是危险的。

现在,如果你打开:),如果没有匹配,那么glob将扩展为空! $ shopt -s nullglob; shopt -u failglob $ for i in *.txt; do mv "$i" "banana$i.txt"; done $ # Oh... nothing happened, great! 。看:

failglob

或者,如果你打开$ shopt -s failglob; shopt -u nullglob $ for i in *.txt; do mv "$i" "banana$i.txt"; done bash: no match: *.txt $ # Good :) ,如果没有匹配,bash会引发错误:

$ shopt -s nullglob failglob
$ for i in *.txt; do mv "$i" "banana$i.txt"; done
bash: no match: *.txt
$ # Good :)

并且循环永远不会被执行(这很好!你不想在不控制其参数的情况下运行命令)。

如果你打开两个怎么办?

failglob

哦,$ # I'm in a directory with no subdirs $ # I'm unsetting nullglob and failglob $ shopt -u nullglob failglob $ array=( */ ) $ declare -p array declare -a array='([0]="*/") $ # Oh dear, my array contains */ verbatim $ # now, let's set nullglob $ shopt -s nullglob $ array=( */ ) $ declare -p array declare -a array='()' $ # Now array is truly empty! :) $ # How about failglob? $ shopt -u nullglob; shopt -s failglob $ # You'll see the failure in $? look: $ echo $? 0 $ # all is good about $? $ array=( */ ) bash: no match: */ $ echo $? 1 $ # :) 似乎赢了。

在你的情况下,如果没有目录,我想你希望你的数组真的是空的。看:

failglob

但是使用$ declare -a array=( some junk in my array ) $ declare -p array declare -a array='([0]="some" [1]="junk" [2]="in" [3]="my" [4]="array")' $ shopt -u nullglob; shopt -s failglob $ array=( */ ) bash: no match: */ $ declare -p array declare -a array='([0]="some" [1]="junk" [2]="in" [3]="my" [4]="array")' $ # Ok, got it! :) ,您的数组将不会重置:

{{1}}