bash:如何从路径中提取任何目录名

huangapple go评论62阅读模式
英文:

bash: How to extract any dirname from the path

问题

想要提取 .../users/**THIS**/random/.... 后的目录名(即 upload、upload2 或 upload3),您可以尝试以下方式:

file=./home/mnt/users/upload/random/reports/on/a/server.md
echo ${file%/*}        # 这将输出完整路径,如:./home/mnt/users/upload/random/reports/on/a
echo $(basename $(dirname $(dirname $file)))    # 这将输出所需的目录名,如:upload

这两行代码中,${file%/*} 用于截取最后一个斜杠 / 之前的部分,然后 $(basename $(dirname $(dirname $file))) 用于提取倒数第三个目录的名称,即您所需的目录名。

英文:

So, I have a few basename such as

./home/mnt/users/upload/random/reports/on/a/server.md
./home/mnt/users/upload2/random/reports/on/a/server.md
./home/mnt/users/upload3/random/reports/on/a/server.md

I want to extract the dirname (look for THIS) after the .../users/**THIS**/random/....
so the output should be either upload, upload2 or upload3

tried with few options such as

file=./home/mnt/users/upload/random/reports/on/a/server.md
echo ${file%/*}
echo $(basename $(dirname $(dirname $file)))

how can I achieve that?

答案1

得分: 2

sed提取具有父目录和子目录/users//random/的目录名称的一种方法:

sed -En 's:.*/users/([^/]+)/random/.*::p';

其中:

  • -E - 启用扩展的正则表达式支持(包括捕获组)
  • -n - 抑制默认打印模式空间内容
  • .*/users/ - 匹配以正则表达式.*/users/开头的部分
  • ([^/]+) - (捕获组 #1) - 匹配任何非 / 字符
  • /random/.* - 匹配以正则表达式/random/.*结尾的部分
  • \1:p - 打印捕获组 #1 的内容

进行测试:

for fname in './home/mnt/users/upload/random/reports/on/a/server.md' './home/mnt/users/upload2/random/reports/on/a/server.md' './home/mnt/users/upload3/random/reports/on/a/server.md';
do
    echo "############ $fname"
    sed -En 's:.*/users/([^/]+)/random/.*::p' <<< "${fname}"
done

这将生成以下结果:

############ ./home/mnt/users/upload/random/reports/on/a/server.md
upload
############ ./home/mnt/users/upload2/random/reports/on/a/server.md
upload2
############ ./home/mnt/users/upload3/random/reports/on/a/server.md
upload3
英文:

One sed approach to extract the name of the directory that has parent and child directories of /users/ and /random/, respectively:

sed -En &#39;s:.*/users/([^/]+)/random/.*::p&#39;

Where:

  • -E - enable extended regex support (and capture groups)
  • -n - suppress default printing of pattern space
  • .*/users/ - match on leading regex .*/users/
  • ([^/]+) - (capture group #1) - match on anything not a /
  • /random/.* - match on trailing regex /random/.*
  • \1:p - print contents of capture group #1

Taking for a test drive:

for fname in &#39;./home/mnt/users/upload/random/reports/on/a/server.md&#39; &#39;./home/mnt/users/upload2/random/reports/on/a/server.md&#39; &#39;./home/mnt/users/upload3/random/reports/on/a/server.md&#39;
do
    echo &quot;############ $fname&quot;
    sed -En &#39;s:.*/users/([^/]+)/random/.*::p&#39; &lt;&lt;&lt; &quot;${fname}&quot;
done

This generates:

############ ./home/mnt/users/upload/random/reports/on/a/server.md
upload
############ ./home/mnt/users/upload2/random/reports/on/a/server.md
upload2
############ ./home/mnt/users/upload3/random/reports/on/a/server.md
upload3

答案2

得分: 0

使用bash的正则表达式操作符(=~):

[[ $pathname =~ /users/([^/]*) ]] && echo "${BASH_REMATCH[1]}"
英文:

With bash's regular expression operator (=~):

[[ $pathname =~ /users/([^/]*) ]] &amp;&amp; echo &quot;${BASH_REMATCH[1]}&quot;

huangapple
  • 本文由 发表于 2023年3月31日 22:33:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/75899743.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定