我想要从我的路径中排除MSG
,PDF
并DOC
使用括号使用 shell 参数扩展。
当我放在MSG
括号之间时,仅删除M
而不是删除MSG
。我在互联网上浏览并阅读了文档,但仍然无法理解如何正确执行此操作。也许我不知道要搜索的正确关键字。
我的代码仅删除味精
find "${INPUTPATH}" -mindepth 2 -maxdepth 2 -type d -print0 | while IFS= read -r -d '' file; do
echo "${file}"
casenumber="${file#${INPUTPATH}/[MSG]}"
echo "${casenumber}"
done
输入:
/home/user/output/test/PDF/2218-0
/home/user/output/test/PDF/2218-0
/home/user/output/test/DOC/2218-0
/home/user/output/test/DOC/2218-0
/home/user/output/test/MSG/2226-4
/home/user/output/test/MSG/2226-4
/home/user/output/test/MSG/2222 -2
/home/user/output/test/MSG/2222 -2
/home/user/output/test/MSG/2218-0
/home/user/output/test/MSG/2218-0
当前删除 MSG 的输出:
/home/user/output/test/PDF/2218-0
/home/user/output/test/PDF/2218-0
/home/user/output/test/DOC/2218-0
/home/user/output/test/DOC/2218-0
/home/user/output/test/MSG/2226-4
SG/2226-4
/home/user/output/test/MSG/2222 -2
SG/2222 -2
/home/user/output/test/MSG/2218-0
SG/2218-0
预期输出:
/home/user/output/test/PDF/2218-0
/home/user/output/test/PDF/2218-0
/home/user/output/test/DOC/2218-0
/home/user/output/test/DOC/2218-0
/home/user/output/test/MSG/2226-4
/2226-4
/home/user/output/test/MSG/2222 -2
/2222 -2
/home/user/output/test/MSG/2218-0
/2218-0
我其实想用这种方式删除MSG、PDF和DOC
find "${INPUTPATH}" -mindepth 2 -maxdepth 2 -type d -print0 | while IFS= read -r -d '' file; do
echo "${file}"
casenumber="${file#${INPUTPATH}/[MSG][PDF][DOC]/}"
echo "${casenumber}"
done
我明白为什么上面的代码不起作用。但我首先需要解决 MSG 才能使这个工作
最终预期输出:
/home/user/output/test/PDF/2218-0
2218-0
/home/user/output/test/DOC/2218-0
2218-0
/home/user/output/test/MSG/2226-4
2226-4
/home/user/output/test/MSG/2222 -2
2222 -2
/home/user/output/test/MSG/2218-0
2218-0
答案1
[MSG]
作为一个全局模式匹配任何一个字符M
,S
或G
。要匹配MSG
、DOC
或PDF
,您可以使用(MSG|DOC|PDF)
inzsh
或@(MSG|DOC|PDF)
in ksh。 bash 不支持 zsh glob 运算符,但它支持 ksh 运算符的子集,包括 after shopt -s extglob
,因此在 bash 中:
shopt -s extglob
casenumber=${file#"${INPUTPATH}"/@(MSG|DOC|PDF)}
将分配给,剥离与 内容匹配的最短前导部分casenumber
的内容(字面上感谢它周围的引号,与 zsh 相反,ksh/bash 中需要这些引号),然后是,或。$file
$INPUTPATH
/
MSG
DOC
PDF
在 ksh 中,只需省略shopt -s extglob
bash 特定且 ksh 中不需要的 。在 zsh 中:
casenumber=${file#$INPUTPATH/(MSG|DOC|PDF)}
答案2
实际上并不是通配符,但是......
=~
当在扩展测试括号中使用时,Bash 的最新版本可以使用其 RegEx 运算符进行基于正则表达式的匹配[[ ... ]]
...它可以执行捕获组(...)
并具有一个内置BASH_REMATCH
数组,其中第零个索引${BASH_REMATCH[0]}
指整个匹配,下一个索引${BASH_REMATCH[1]}
指第一个捕获组匹配,下一个${BASH_REMATCH[2]}
指第二个捕获组匹配,依此类推。
所以,你可能会做这样的事情:
$ printf '%s\0' "/home/user/output/test/PDF/2218-0" "/home/user/output/test/DOC/2218-0" "/home/user/output/test/MSG/2226-4" |
while IFS= read -r -d '' file; do
[[ "$file" =~ .*(DOC|MSG|PDF)(.*) ]] && printf '%s\n' "$file" "${BASH_REMATCH[2]}"
done
/home/user/output/test/PDF/2218-0
/2218-0
/home/user/output/test/DOC/2218-0
/2218-0
/home/user/output/test/MSG/2226-4
/2226-4
答案3
不是回答你的确切问题,而是关于这个特殊案例的一些注释。
鉴于您在find "${INPUTPATH}" -mindepth 2 -maxdepth 2
那里,所有生成的路径在初始路径之后应该只有一个斜杠$INPUTPATH
,因此您可以忽略那里有哪个特定的三字母字符串,而只删除下一个之前的任何内容/
:
casenumber=${file#"${INPUTPATH}"/*/}
或者,因为它是最后一个斜杠,所以只需删除一切直到最后/
:
casenumber="${file##*/}"
在这里,加倍#
意味着采取最长的比赛。
另外,如果您先在运行之前,您可以$INPUTPATH
从输出中删除该部分(仅将其替换为 ) :.
cd
find
(cd -P -- "${INPUTPATH}" && find . -mindepth 2 -maxdepth 2 -type d -print0) |
while IFS= read -r -d '' file; do
echo "${file}"
casenumber="${file#./*/}"
echo "${casenumber}"
done