【问题标题】:how to replace all substrings of a array of strings in bash?如何替换bash中字符串数组的所有子字符串?
【发布时间】:2021-06-23 09:05:20
【问题描述】:

我试图在没有路径的情况下列出子目录中的所有文件,我只想要文件名和扩展名,但是 Bash 替换不适用于数组中的所有路径,它只适用于第一个元素.

代码:

#!/usr/bin/bash

NAME="$(pwd | grep -o '[^/]*$')"

# ls src -R
PATH="$(ls src/*.{cpp,hpp} 2> /dev/null)"
if [ 0 -eq "${#PATH[@]}" ]; then
    echo "The project has no source code file yet."
    exit 0
fi

EMPTY=''
for FILE in "${PATH[@]}"; do
    echo "${FILE/src\//$EMPTY}"
done

目录树:

FileReader
├── bin
├── make.sh
├── obj
└── src
    ├── FileReader.cpp
    ├── FileReader.hpp
    └── main.cpp

预期:

$ bash make.sh

FileReader.cpp
FileReader.hpp
main.cpp

输出:

$ bash make.sh

FileReader.cpp
src/FileReader.hpp
src/main.cpp

【问题讨论】:

  • 你能用这个吗-( cd src ; ls *.{cpp,hpp} )
  • 或者找-printf "%f\n"
  • 将您的代码粘贴到shellcheck.net
  • 看看dirname,也避免在bash中使用大写变量以避免varname冲突,PATH已经被占用了。代码中的 PATH 也不是数组。
  • @MrR 感谢您的解决方案,它成功了!

标签: bash scripting text-processing string-substitution


【解决方案1】:

因为parsing ls is bad,我会做这样的事情:

#!/usr/bin/env bash

# If no matching files, globs expand to an empty string instead of the pattern
shopt -s nullglob
declare -i count=0
for file in src/*.[ch]pp; do
    count+=1
    printf "%s\n" "$(basename "$file")"
done

[[ $count -eq 0 ]] && echo "The project has no source code file yet."

避免文件名中出现有趣字符的问题。 basename(1) 从文件名中删除前导目录组件(以及可选的给定扩展名)。

您还可以使用files=( src/*.[ch]pp ) 安全地获取数组中的文件,并使用更接近原始方法的方法。我会肯定避免调用变量PATH,因为这与内置变量冲突。

基于数组的版本(此版本使用${variable#pattern} 参数扩展语法,从变量值的开头剥离模式的匹配文本):

#!/usr/bin/env bash

shopt -s nullglob
files=( src/*.[ch]pp )

if [[ "${#files[@]}" -eq 0 ]]; then
    echo "The project has no source code file yet."
else
    printf "%s\n" "${files[@]#*/}"
fi

【讨论】:

  • 实际上,我更喜欢第二个版本,因为它删除了显式的 for 循环。
  • 并删除所有要执行的子进程basename,因此如果有很多文件应该更快。
猜你喜欢
  • 1970-01-01
  • 2012-08-09
  • 2022-01-11
  • 2012-08-01
  • 2015-02-05
  • 2014-05-18
  • 2017-01-13
  • 2022-11-21
  • 1970-01-01
相关资源
最近更新 更多