bash 在向数组添加元素时添加前缀和后缀特殊字符

Ahm*_*mFM 0 arrays bash arraylist

团队,如何重新创建带有前缀和后缀字符的数组是我的要求,不包括第一个索引。

我正在创建一个元素字符串,但不知何故它正在消失s。我怎样才能避免这种情况?有没有更好的方法来添加我想要的内容?

elements_string="src/common src/common/access/ src/common/deny/"

我正在创建下面的new数组,其中包含开始index 1排除索引 0 的所有元素。然后在添加它们时我希望它们带有前缀和后缀。

for ele in $elements_string
do
    bazel_apps_list=$(find $ele -type f -name 'BUILD.bazel' | sed -r 's|/[^/]+$||' |sort |uniq)
   new+=(-//${bazel_apps_list[@]:1}/...)
done
Run Code Online (Sandbox Code Playgroud)

输出:src 中缺少 s 字母。

-//rc/common/access/...
Run Code Online (Sandbox Code Playgroud)

像下面这样查看前缀-//和后缀...

预期产出 new=(-//src/common/access/... -//src/common/deny/...)

基本上,我需要将这些传递给 bazel 覆盖命令,所以需要。

bazel coverage ${new[@]}

我尝试了下面的答案

#!/bin/bash
apps_str="$(ls -d src/common/*/)"
echo $apps_str
if [ ! -z "${apps_str}" ]; then
    for APP in $apps_str
    do  
        bazel_apps_array=("$(find $APP -type f -name 'BUILD.bazel' | sed -r 's|/[^/]+$||' |sort |uniq)")
        app_parent_dir=${bazel_apps_array[0]}
        app_child_dirs=${bazel_apps_array[@]:1}
        mapfile -t -d '' skip_app_child_dirs < <( find $app_child_dirs -type f -name 'BUILD.bazel' -printf '-//%h/...\0' )
        #bazel coverage $app_parent_dir $skip_app_child_dirs
    echo -e "bazel coverage $app_parent_dir ${skip_app_child_dirs[@]}"
    done
else
    printf "\nAPP %s Parent dir is not bazel buildable, hence skip it.\n"
fi
Run Code Online (Sandbox Code Playgroud)

输出

src/common/access/ src/common/args/ src/common/zaputil/ 

./t.sh: line 10: mapfile: -d: invalid option
mapfile: usage: mapfile [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]

./t.sh: line 10: mapfile: -d: invalid option
mapfile: usage: mapfile [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
bazel src/common/access
.
.
.


Run Code Online (Sandbox Code Playgroud)

预期产出

bazel coverage src/common/access -//src/common/access/v1/... -//src/common/access/v2/...
Run Code Online (Sandbox Code Playgroud)

Ren*_*let 5

由于您的bazel_apps_list是标量(不是数组),${bazel_apps_list[@]}因此与 相同$bazel_apps_list。而且您显然认为它${bazel_apps_list[@]:1}会作为数组的第一个元素展开,而它会随着$bazel_apps_list第一个字符的删除而展开,或者更准确地说,从第二个字符(编号为 1)到字符串末尾(默认)。如果bazel_apps_list是索引数组,您可能会使用 访问它的第一个元素${bazel_apps_list[0]}

无论如何,GNU find(如果它是您使用的)是如此强大,以至于当您的脚本多次运行它并对其输出进行后处理时,有可能存在一种更简单的解决方案,只需一次调用且无需后处理。

你可以试试:

elements_string=("src/common" "src/common/access/" "src/common/deny/")
mapfile -t -d '' new < <( find "${elements_string[@]}" -type f -name 'BUILD.bazel' -printf '-//%h/...\0' )
Run Code Online (Sandbox Code Playgroud)

我们使用索引数组elements_string代替字符串,-d ''选项mapfile-printf '...\0'操作find以防文件名中包含空格或换行符。后两者使用 NUL 字符作为分隔符,即唯一在文件名中找不到的字符。

将结果传递给时,即使有空格或换行符,也bazel不要忘记周围的引号,以便每个元素恰好获得一个单词:${new[@]}

bazel coverage "${new[@]}"
Run Code Online (Sandbox Code Playgroud)

如果文件名中没有空格或换行符,您可以尝试稍微简单的方法:

elements_string="src/common src/common/access/ src/common/deny/"
new=( $(find $elements_string -type f -name 'BUILD.bazel' -printf '-//%h/...\n') )
Run Code Online (Sandbox Code Playgroud)