Bash:从两端修剪参数

发布于 2024-09-05 11:13:24 字数 264 浏览 12 评论 0原文

问候!

这是众所周知的 Bash 参数扩展模式:

${parameter#word}${parameter##word}

${parameter%word} >, ${parameter%%word}

我需要从参数的开头截取一部分,并从参数的末尾截取另一部分。您能为我提供一些建议吗?

Greetings!

This are well know Bash parameter expansion patterns:

${parameter#word}, ${parameter##word}

and

${parameter%word}, ${parameter%%word}

I need to chop one part from the beginning and anoter part from the trailing of the parameter. Could you advice something for me please?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

洒一地阳光 2024-09-12 11:13:33

我强烈建议使用 bash 数组,因为它们的性能比正则表达式匹配快 3 倍多。

$ path='/xxx/yyy/zzz/ABC/abc.txt'
$ IFS='/' arr=( $path )
$ echo ${arr[${#arr[@]}-2]}
ABC

这是通过 IFS='/' 告诉 bash 数组的每个元素由正斜杠 / 分隔的。我们首先通过 ${#arr[@]} 确定数组中有多少个元素,然后减去 2 并将其用作数组的索引,从而访问数组的倒数第二个元素。

I would highly recommend going with bash arrays as their performance is just over 3x faster than regular expression matching.

$ path='/xxx/yyy/zzz/ABC/abc.txt'
$ IFS='/' arr=( $path )
$ echo ${arr[${#arr[@]}-2]}
ABC

This works by telling bash that each element of the array is separated by a forward slash / via IFS='/'. We access the penultimate element of the array by first determining how many elements are in the array via ${#arr[@]} then subtracting 2 and using that as the index to the array.

一抹微笑 2024-09-12 11:13:31

该解决方案使用 Andrey 所要求的内容,并且不使用任何外部工具。策略:使用 % 参数扩展删除文件名,然后使用 ## 删除除最后一个目录之外的所有目录:

$ path=/path/to/my/last_dir/filename.txt

$ dir=${path%/*}     

$ echo $dir
/path/to/my/last_dir

$ dir=${dir##*/}

$ echo $dir
last_dir

This solution uses what Andrey asked for and it does not employ any external tool. Strategy: Use the % parameter expansion to remove the file name, then use the ## to remove all but the last directory:

$ path=/path/to/my/last_dir/filename.txt

$ dir=${path%/*}     

$ echo $dir
/path/to/my/last_dir

$ dir=${dir##*/}

$ echo $dir
last_dir
少女的英雄梦 2024-09-12 11:13:30

我不知道有没有一种简单的方法可以在不诉诸子 shell 的情况下完成此操作,为了提高效率,您可能希望避免使用子 shell。我只会使用:

> xx=hello_there
> yy=${xx#he}
> zz=${yy%re}
> echo ${zz}
llo_the

如果您不关心效率并且只想要一句话:

> zz=$(echo ${xx%re} | sed 's/^he//')
> echo ${zz}
llo_the

请记住,第二种方法启动子 shell - 如果您的脚本必须运行,我不会做很多事情快速地。

I don't know that there's an easy way to do this without resorting to sub-shells, something you probably want to avoid for efficiency. I would just use:

> xx=hello_there
> yy=${xx#he}
> zz=${yy%re}
> echo ${zz}
llo_the

If you're not fussed about efficiency and just want a one-liner:

> zz=$(echo ${xx%re} | sed 's/^he//')
> echo ${zz}
llo_the

Keep in mind that this second method starts sub-shells - it's not something I'd be doing a lot of if your script has to run fast.

耳根太软 2024-09-12 11:13:27

如果您使用的 Bash 版本 >= 3.2,则可以使用正则表达式与捕获组匹配来检索一个命令中的值:

$ path='/xxx/yyy/zzz/ABC/abc.txt'
$ [[ $path =~ ^.*/([^/]*)/.*$ ]]
$ echo ${BASH_REMATCH[1]}
ABC

这相当于:

$ path='/xxx/yyy/zzz/ABC/abc.txt'
$ path=$(echo "$path" | sed 's|^.*/\([^/]*\)/.*$|\1|p')
$ echo $path
ABC

If you're using Bash version >= 3.2, you can use regular expression matching with a capture group to retrieve the value in one command:

$ path='/xxx/yyy/zzz/ABC/abc.txt'
$ [[ $path =~ ^.*/([^/]*)/.*$ ]]
$ echo ${BASH_REMATCH[1]}
ABC

This would be equivalent to:

$ path='/xxx/yyy/zzz/ABC/abc.txt'
$ path=$(echo "$path" | sed 's|^.*/\([^/]*\)/.*$|\1|p')
$ echo $path
ABC
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文