我已经在bash脚本中以字符串形式生成了一组文件路径,所有形式都是这样:
./foo/bar/filename.proto
可以有任意数量的子文件夹/斜杠,但是它们都具有.proto
扩展名。
我想修剪./
开头和结尾的filename.proto
使其看起来像这样:
foo/bar
从其他解决方案改编和调试它的难度令人惊讶。我尝试过:
grep -Po "\.\/(.*)\/[^\/]+\.proto"
和
sed -n 's/\.\/\(.*\)\/[^\/]+\.proto/\1/p'
我尝试用转义和未转义的括号进行sed。供参考,我目前正在Mac上工作,并且想要最跨平台兼容的解决方案。
我可以在Python中相当容易地做到这一点,但我想避免调用另一个脚本来完成此工作的复杂性。
要让您了解其工作原理,到目前为止,我的完整脚本如下所示:
#!/bin/bash
consume_single_folder () {
do_stuff $1
}
find . -name \*.proto|while read fname; do
echo "$fname" |sed -n 's/\.\/\(.*\)\/[^\/]+\.proto/\1/p' | consume_single_folder
done
感谢您的帮助。谢谢!
编辑:
要清楚,我已经在regex101.com上测试了我的正则表达式,看起来还不错:
\.\/(.*)\/[^\/]+\.proto
应该贪婪,捕获第一个和最后一个斜杠之间的所有内容。
答案 0 :(得分:1)
看起来像dirname
可以帮助您:
$ dirname "./foo/bar/filename.proto"
./foo/bar
在./
前被删除:
$ dirname "./foo/bar/filename.proto" | sed "s/\.\///g"
foo/bar
您还可以添加sort | uniq
避免重复:
find . -name \*.proto|while read fname; do
echo "$fname" | xargs dirname | sed "s/\.\///g" | consume_single_folder
done
在MacOS和Linux上运行
答案 1 :(得分:1)
请不要使用regex101之类的网站来测试sed
正则表达式-工具之间以及各种实现之间的语法和功能差异很大。请参见Why does my regular expression work in X but not in Y?和differences between various sed implementations < / p>
对于您给定的示例,将+
更改为*
将起作用(BRE和ERE之间的查找差异)
$ fname='./foo/bar/filename.proto'
$ echo "$fname" | sed -n 's/\.\/\(.*\)\/[^\/]*\.proto/\1/p'
foo/bar
$ # or use a different delimiter
$ echo "$fname" | sed 's|\./\(.*\)/[^/]*\.proto|\1|'
foo/bar
$ # further simplification as find already filters by extension
$ echo "$fname" | sed 's|\./\(.*\)/.*|\1|'
foo/bar
此外,我建议您阅读Why is looping over find's output bad practice?并相应地更改find
的语法