我知道这可以像我在https://stackoverflow.com/a/33379831/3962126上回答的那样使用正则表达式轻松完成,但我需要在bash中执行此操作。
所以我发现Stackoverflow上最接近的问题就是这个问题bash: extracting last two dirs for a pathname,但区别在于如果
DIRNAME = /a/b/c/d/e
然后我需要提取
d
答案 0 :(得分:5)
这可能相对较长,但执行速度比大多数前面的答案要快得多(除了zsh-only和ja之外),因为它只使用内置于bash中的字符串操作而不使用子shell扩展:< / p>
string='/a/b/c/d/e' # initial data
dir=${string%/*} # trim everything past the last /
dir=${dir##*/} # ...then remove everything before the last / remaining
printf '%s\n' "$dir" # demonstrate output
上面使用了 printf
,因为echo
对所有值都不能可靠地工作(考虑它在/a/b/c/-n/e
的GNU系统上会做什么)。
答案 1 :(得分:4)
这是一个纯粹的bash
解决方案:
[[ $DIRNAME =~ /([^/]+)/[^/]*$ ]] && printf '%s\n' "${BASH_REMATCH[1]}"
与其他一些答案相比:
d
它不匹配DIRNAME=d/e
。另请注意,这不是在bash
中分配变量的方式:
DIRNAME = /a/b/c/d/e
^ ^
这些空格是错误的,所以删除它们:
DIRNAME=/a/b/c/d/e
答案 2 :(得分:1)
dir=$(basename -- "$(dirname -- "$str")")
echo "$dir"
答案 3 :(得分:1)
使用awk
:
echo "/a/b/c/d/e" | awk -F / '{ print $(NF-1) }' # d
编辑:当路径包含换行符时,这不起作用,并且当少于两个斜杠时仍然提供输出,请参阅下面的注释。
答案 4 :(得分:0)
使用sed
如果你想获得第四个元素
DIRNAME="/a/b/c/d/e"
echo "$DIRNAME" | sed -r 's_^(/[^/]*){3}/([^/]*)/.*$_\2_g'
如果你想获得前一个元素
DIRNAME="/a/b/c/d/e"
echo "$DIRNAME" | sed -r 's_^.*/([^/]*)/[^/]*$_\1_g'
答案 5 :(得分:-1)
使用zsh参数替换也很酷
echo ${${DIRNAME%/*}##*/}
我认为它比双$()更快,因为它不需要任何子流程。
基本上它首先从右侧切掉,然后将剩下的所有左侧切掉。