【问题标题】:How do you alter the contents of an array with sed in BASH shell script?如何在 BASH shell 脚本中使用 sed 更改数组的内容?
【发布时间】:2015-01-28 00:02:59
【问题描述】:

我在当前目录中创建了一个以 .cpp 结尾的所有文件的名称数组,并希望创建相同的数组,并将 .cpp 替换为 .o

cppfield=$(ls *.cpp)
ofield=$(ls *.cpp | awk '{print}' ORS=' ' | sed s/.cpp/.o/g)

但它不起作用,只有第一个参数将 .cpp 与 .o 切换

【问题讨论】:

  • 令人惊讶的是我无法复制它。
  • cppfield=$(ls *.cpp) 不创建数组而是创建字符串。如果你想要一个数组使用cppfield(*.cpp)。它实际上创建了一个数组并允许您使用带有空格/等的文件名。安全。
  • @EtanReisner 在使用cppfield=($(ls -1 *.cpp)) 时,我会将IFS 更改为IFS=$'\n'。我在你的 sn-p > cppfield(*.cpp) 中缺少什么以避免单独处理带有空格的文件?
  • IFS 混淆只是问题的一部分。我不确定我是否理解第二个问题。
  • “让您安全地使用带有空格/等的文件名”让我担心。我认为创建数组时文件名中的默认 IFS 和空格存在问题。你的 sn-p 真的能处理吗?如果是这样,为什么?希望我的问题现在更清楚了。

标签: arrays bash shell sed


【解决方案1】:

扩展数组时可以使用模式替换:

bash> a=(a.cpp b.cpp);
bash> a=("${a[@]/%.cpp/.o}");
bash> echo "${a[@]}";
a.o b.o

【讨论】:

    【解决方案2】:

    这就是你想要做的。

    $ ls
    a1.cpp  a2.cpp  a3.cpp  a4.cpp  a5.cpp  a6.cpp
    $ cppfield=(*.cpp)
    $ declare -p cppfield
    declare -a cppfield='([0]="a1.cpp" [1]="a2.cpp" [2]="a3.cpp" [3]="a4.cpp" [4]="a5.cpp" [5]="a6.cpp")'
    $ ofield=("${cppfield[@]/%.cpp/.o}")
    $ declare -p ofield
    declare -a ofield='([0]="a1.o" [1]="a2.o" [2]="a3.o" [3]="a4.o" [4]="a5.o" [5]="a6.o")'
    

    使用 globbing 填充数组以安全地处理文件名。 Don't parse ls

    使用Shell Parameter Expansion 将每个数组元素上的.cpp 替换为.o

    用引号扩展一个数组并将结果存储在一个新数组中。

    【讨论】:

      【解决方案3】:

      不要使用ls 来获取目录内容以进行进一步处理。很难正确处理包含空格和换行符的文件名。

      最好像这样使用find

      x() { sed 's/\.cpp$/.o/' <<< "$1"; }
      export -f x
      find . -maxdepth 1 -exec bash -c 'x "{}"' \;
      

      现在答案不再是关于数组,但那是因为我想指出将ls 的输出存储在数组中已经是问题的开始。也许完全避免使用数组来完成这项任务。

      【讨论】:

        猜你喜欢
        • 2014-11-01
        • 2017-04-03
        • 2013-05-27
        • 2019-02-24
        • 1970-01-01
        • 2014-01-09
        • 2023-01-12
        • 2014-08-20
        • 2023-03-16
        相关资源
        最近更新 更多