给定由空格分隔的路径字符串:
path/folderA/fileA1 path/folderA/subFolderA/fileA2 path/folderB/fileB1
我想要一个由空格分隔的路径字符串,只有以path/folderA/开头的路径
输出:path/folderA/fileA1 path/folderA/subFolderA/fileA2
然后从该字符串中删除路径/folderA/的任何匹配项
最终输出:fileA1 subFolderA/fileA2
这能用一行完成吗?
如果你从一个字符串开始,那么嵌入的空格、换行符或其他有问题的字符可能会出错。这就是为什么使用globs或null终止值通常更好的原因。
也就是说,您可以使用各种内置和扩展来从给定的示例中获得您想要的结果。请注意,必须正确转义正斜杠或将其存储在带引号的字符串中,以避免干扰扩展语法。例如:
path_str="path/folderA/fileA1 path/folderA/subFolderA/fileA2 path/folderB/fileB1"
match_str="path/folderA/"
read -ra paths <<< "$path_str"
for i in "${!paths[@]}"; do
[[ ! "${paths[i]}" =~ $match_str ]] && unset paths[i]
done
echo "${paths[@]//$match_str}"
这将打印:
fileA1 subFolderA/fileA2
使用grep
。
echo " $str" | grep -oP '(?<=spath/folderA/)S+' | xargs
-P
允许使用Perl正则表达式语法,您可以使用(?<=pattern)
,这是一个积极的前瞻性断言。此外,-o
只保留该模式之后的匹配部分,即S+
,一系列非空白字符(直到我们找到下一个空格、制表符、换行符等(
此外,grep
输出总是用换行符分隔,因此您必须通过管道连接到tr 'n' ' '
或xargs
或类似的文件才能得到一行。
编辑:为了只匹配路径的开头,我添加了s
(一个空白字符(,并将输入作为" $str"
提供。这似乎更容易解决,因为b
也匹配/
,而(^|s)
抛出grep: lookbehind assertion is not fixed length
。所以用这个测试是可以的:
> echo "$str"
path/folderA/fileA1 path/folderA/subfolderA/fileA2 path/path/folderA/not
> echo " $str" | grep -owP '(?<=spath/folderA/)S+' | xargs
fileA1 subFolderA/fileA2
您可以简单地使用awk
来匹配每个字段中的最后一组单词字符并输出它们,例如
awk '{for (i=1; i<=NF; i++) if ($i ~ /folderA/) { match($i,/w+$/); print substr($i,RSTART,RLENGTH)}}' <<< $path_str
示例使用/输出
path_str="path/folderA/fileA1 path/folderA/subFolderA/fileA2 path/folderB/fileB1"
awk '{for (i=1; i<=NF; i++) if ($i ~ /folderA/) { match($i,/w+$/); print substr($i,RSTART,RLENGTH)}}' <<< $path_str
fileA1
fileA2
您可以根据需要调整输出格式。如果您希望输出全部在一行上,或者如果您希望使用命令替换在新数组中捕获输出,则由您决定。
使用Bash参数展开
如果您想使用参数扩展和子串删除,您可以使用一个简单的循环和扩展$(var##*/}
从每个路径组件中删除所有内容,直到最后的'/'
,例如
path_str="path/folderA/fileA1 path/folderA/subFolderA/fileA2 path/folderB/fileB1"
for i in $path_str; do
[[ $i =~ folderA ]] && echo ${i##*/}
done
fileA1
fileA2
对于您的情况,参数扩展可能是最有效的,因为它是shell的内置功能,可以避免生成子shell。然而,如果您有几十万个组件,那么我可能会让awk
来处理它。
带有子字符串删除的符合POSIX的参数扩展集为:
${var#pattern} Strip shortest match of pattern from front of $var
${var##pattern} Strip longest match of pattern from front of $var
${var%pattern} Strip shortest match of pattern from back of $var
${var%%pattern} Strip longest match of pattern from back of $var
除了POSIX提供的参数扩展之外,Bash还提供了更多的参数扩展。包括从子字符串替换到字符大小写转换的所有内容。
如果您还有其他问题,请告诉我。