使用 bash 将文件夹名称保存为循环中的变量
Save folder name as variable in a loop using bash
我有多个文件夹,我试图将每个文件夹名称保存为一个变量,供下游循环使用:
for f in TINKER*;
do
name=$(echo $f | sed 's/TINKER_more([0-9]+)_less([0-9]+)/TINKER__/')
echo $name
done
文件夹示例:
TINKER_more05_less23
TINKER_more55_less218
TINKER_more23_less03
上面第一个文件夹的情况,我要echo $name输出:TINKER_05_23
出于某种原因,我一直从 echo $name 得到空输出。
有人能帮忙吗?谢谢
POSIX BRE 正则表达式中的 +
匹配文字 +
字符。您需要添加 -E
选项以使 sed
使用 POSIX ERE 语法。
此外,您需要在替换中使用\n
,而不是$n
。 perl
使用 $n
替换反向引用语法,但 sed
使用 \n
.
所以你需要
sed -E 's/TINKER_more([0-9]+)_less([0-9]+)/TINKER__/'
当testing有以上数据时,
fldrs="TINKER_more05_less23 TINKER_more23_less03 TINKER_more55_less218"
for f in $fldrs; do
name=$(echo "$f" | sed -E 's/TINKER_more([0-9]+)_less([0-9]+)/TINKER__/');
# OR
# name=$(sed -E 's/TINKER_more([0-9]+)_less([0-9]+)/TINKER__/' <<< "$f");
echo "$name"
done
输出为
TINKER_05_23
TINKER_23_03
TINKER_55_218
另外,如果你想纯Bash:
rx='TINKER_more([[:digit:]]+)_less([[:digit:]]+)'
for f in TINKER*; do
if [[ "$f" =~ $rx ]]; then
echo "TINKER_${BASH_REMATCH[1]}_${BASH_REMATCH[2]}"
fi
done
再次查看 this online demo 产生 TINKER_05_23
、TINKER_23_03
和 TINKER_55_218
。
TINKER_more([[:digit:]]+)_less([[:digit:]]+)
正则表达式包含两个用两对非转义括号定义的捕获组,以及
${BASH_REMATCH[1]}
包含第 1 组的内容,${BASH_REMATCH[2]}
包含第 2 组的值。
使用sed
$ name=$(sed 's/_[^0-9]*\([^_]*\)/_/g' <<< $f)
Bash 有一个 built-in 匹配运算符 =~
,因此您不需要 sed
。您可以使用纯 Bash 编写代码段,如下所示:
for f in TINKER*; do
if [[ $f =~ TINKER_more([0-9]+)_less([0-9]+) ]]; then
echo TINKER_${BASH_REMATCH[1]}_${BASH_REMATCH[2]}
fi
done
以上代码将为您发布的文件生成以下输出:
TINKER_05_23
TINKER_23_03
TINKER_55_218
我有多个文件夹,我试图将每个文件夹名称保存为一个变量,供下游循环使用:
for f in TINKER*;
do
name=$(echo $f | sed 's/TINKER_more([0-9]+)_less([0-9]+)/TINKER__/')
echo $name
done
文件夹示例:
TINKER_more05_less23
TINKER_more55_less218
TINKER_more23_less03
上面第一个文件夹的情况,我要echo $name输出:TINKER_05_23
出于某种原因,我一直从 echo $name 得到空输出。
有人能帮忙吗?谢谢
POSIX BRE 正则表达式中的 +
匹配文字 +
字符。您需要添加 -E
选项以使 sed
使用 POSIX ERE 语法。
此外,您需要在替换中使用\n
,而不是$n
。 perl
使用 $n
替换反向引用语法,但 sed
使用 \n
.
所以你需要
sed -E 's/TINKER_more([0-9]+)_less([0-9]+)/TINKER__/'
当testing有以上数据时,
fldrs="TINKER_more05_less23 TINKER_more23_less03 TINKER_more55_less218"
for f in $fldrs; do
name=$(echo "$f" | sed -E 's/TINKER_more([0-9]+)_less([0-9]+)/TINKER__/');
# OR
# name=$(sed -E 's/TINKER_more([0-9]+)_less([0-9]+)/TINKER__/' <<< "$f");
echo "$name"
done
输出为
TINKER_05_23
TINKER_23_03
TINKER_55_218
另外,如果你想纯Bash:
rx='TINKER_more([[:digit:]]+)_less([[:digit:]]+)'
for f in TINKER*; do
if [[ "$f" =~ $rx ]]; then
echo "TINKER_${BASH_REMATCH[1]}_${BASH_REMATCH[2]}"
fi
done
再次查看 this online demo 产生 TINKER_05_23
、TINKER_23_03
和 TINKER_55_218
。
TINKER_more([[:digit:]]+)_less([[:digit:]]+)
正则表达式包含两个用两对非转义括号定义的捕获组,以及
${BASH_REMATCH[1]}
包含第 1 组的内容,${BASH_REMATCH[2]}
包含第 2 组的值。
使用sed
$ name=$(sed 's/_[^0-9]*\([^_]*\)/_/g' <<< $f)
Bash 有一个 built-in 匹配运算符 =~
,因此您不需要 sed
。您可以使用纯 Bash 编写代码段,如下所示:
for f in TINKER*; do
if [[ $f =~ TINKER_more([0-9]+)_less([0-9]+) ]]; then
echo TINKER_${BASH_REMATCH[1]}_${BASH_REMATCH[2]}
fi
done
以上代码将为您发布的文件生成以下输出:
TINKER_05_23
TINKER_23_03
TINKER_55_218