bash 使用 sed 或 awk 从绝对路径中提取目录名称
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8560295/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Extracting directory name from an absolute path using sed or awk
提问by AruM
I want to split this line
我想分割这条线
/home/edwprod/abortive_visit/bin/abortive_proc_call.ksh
to
到
/home/edwprod/abortive_visit/bin
using sed
or awk
scripts? Could you help on this?
使用sed
或awk
脚本?你能帮忙吗?
采纳答案by 4ndrew
May be command dirnameis what you searching for?
可能是命令dirname是您要搜索的内容?
dirname /home/edwprod/abortive_visit/bin/abortive_proc_call.ksh
Or if you want sed, so see my solution:
或者,如果您想要 sed,请参阅我的解决方案:
echo /home/edwprod/abortive_visit/bin/abortive_proc_call.ksh | sed 's/\(.*\)\/.*//'
回答by Kent
dirname
目录名
kent$ dirname "/home/edwprod/abortive_visit/bin/abortive_proc_call.ksh"
/home/edwprod/abortive_visit/bin
sed
sed
kent$ echo "/home/edwprod/abortive_visit/bin/abortive_proc_call.ksh"|sed 's#/[^/]*$##'
/home/edwprod/abortive_visit/bin
grep
格雷普
kent$ echo "/home/edwprod/abortive_visit/bin/abortive_proc_call.ksh"|grep -oP '^/.*(?=/)'
/home/edwprod/abortive_visit/bin
awk
awk
kent$ echo "/home/edwprod/abortive_visit/bin/abortive_proc_call.ksh"|awk -F'/[^/]*$' '{print }'
/home/edwprod/abortive_visit/bin
回答by wangzhengyi
awk + for :
awk + 为:
echo "/home/edwprod/abortive_visit/bin/abortive_proc_call.ksh" | awk 'BEGIN{res=""; FS="/";}{ for(i=2;i<=NF-1;i++) res=(res"/"$i);} END{print res}'
回答by caret
This code with awkwill work perfectly as same as dirname, I guess.
我猜,这段带有awk 的代码将与dirname完美地工作。
It's so simple and has very low cost to work. Good luck.
它是如此简单,而且工作成本非常低。祝你好运。
Code
代码
$ foo=/app/java/jdk1.7.0_71/bin/java
$ echo "$foo" | awk -F "/*[^/]*/*$" '
{ print ( == "" ? (substr($ echo $foo | awk '{
dirname = gensub("/*[^/]*/*$", "", "", awk 'BEGIN{FS=OFS="/"}{NF--}1'
);
print (dirname == "" ? (substr(awk 'BEGIN{FS=OFS="/"}{gsub("/+","/")}
{s=| path | dirname | awk full | awk short |
|------------+---------+----------+-----------|
| . | . | . | |
| / | / | / | |
| foo | . | . | |
| foo/ | . | . | foo |
| foo/bar | foo | foo | foo |
| foo/bar/ | foo | foo | foo/bar |
| /foo | / | / | |
| /foo/ | / | / | /foo |
| /foo/bar | /foo | /foo | /foo |
| /foo/bar/ | /foo | /foo | /foo/bar |
| /foo///bar | /foo | /foo | /foo// |
~/^\//;NF-=$NF?1:2;dirname /home/edwprod/abortive_visit/bin/abortive_proc_call.ksh
=str="/home/edwprod/abortive_visit/bin/abortive_proc_call.ksh"
echo "$str" | sed -n -e '1p' | sed -e 's#//*#/#g' -e 's#\(.\)/$##' -e 's#^[^/]*$#.#' -e 's#\(.\)/[^/]*$##' -
?echo "$str" | awk -F"/" '{print $NF}' -
:(s?"/":".")};1' <file>
, 1, 1) == "/" ? "/" : ".") : dirname);
}'
, 1, 1) == "/" ? "/" : ".") : ); }'
Result
结果
/app/java/jdk1.7.0_71/bin
/app/java/jdk1.7.0_71/bin
Test
测试
foo=/app/java/jdk1.7.0_71/bin/java
->/app/java/jdk1.7.0_71/bin
foo=/app/java/jdk1.7.0_71/bin/
->/app/java/jdk1.7.0_71
foo=/app/java/jdk1.7.0_71/bin
->/app/java/jdk1.7.0_71
foo=/app/
->/
foo=/app
->/
foo=fighters/
->.
foo=/app/java/jdk1.7.0_71/bin/java
->/app/java/jdk1.7.0_71/bin
foo=/app/java/jdk1.7.0_71/bin/
->/app/java/jdk1.7.0_71
foo=/app/java/jdk1.7.0_71/bin
->/app/java/jdk1.7.0_71
foo=/app/
->/
foo=/app
->/
foo=fighters/
->.
More
更多的
If you're not available such awk delimiter, try it this way.
如果您没有这样的 awk 分隔符,请尝试这种方式。
##代码##回答by kvantour
In addition, to the answer of Kent, an alternative awk solution is:
此外,对于 Kent 的回答,另一种 awk 解决方案是:
##代码##which has the same sickness as the one presented by Kent. The following, somewhat longer Awk corrects all the flaws:
它与肯特提出的疾病具有相同的疾病。以下稍长的 awk 纠正了所有缺陷:
##代码##The following table shows the difference:
下表显示了差异:
##代码##note:dirname
is the real way to go, unless you have to process masses of them stored in a file.
注意:dirname
是真正的方法,除非您必须处理存储在文件中的大量文件。
回答by Роман Коптев
For most platforms and Unix/Linux shells now available dirname
:
对于现在可用的大多数平台和 Unix/Linux shell dirname
:
Using of dirname
is the simpliest way, but it is not recommended for cross platform scripting for example in the last version of autoconf
documentation http://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Limitations-of-Usual-Tools.html#Limitations-of-Usual-Tools.
使用 ofdirname
是最简单的方法,但不推荐用于跨平台脚本,例如在最新版本的autoconf
文档http://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/ Limitations-of-Usual-Tools.html#Limitations-of-Usual-Tools。
So my full featured version of sed
-based alternative for dirname
:
所以我的全功能版本sed
-based 替代方案dirname
:
Examples:
例子:
It works like dirname
:
它的工作原理如下dirname
:
- For path like
/aa/bb/cc
it will print/aa/bb
- For path like
/aa/bb
it will print/aa
- For path like
/aa/bb/
it will print/aa
too. - For path like
/aa/
it will print/aa
- For path like
/
it will print/
- For path like
aa
it will print.
- For path like
aa/
it will print.
- 对于像
/aa/bb/cc
它会打印的路径/aa/bb
- 对于像
/aa/bb
它会打印的路径/aa
- 对于像
/aa/bb/
它这样的路径也会打印/aa
。 - 对于像
/aa/
它会打印的路径/aa
- 对于像
/
它会打印的路径/
- 对于像
aa
它会打印的路径.
- 对于像
aa/
它会打印的路径.
That is:
那是:
- It works correct with trailing
/
- It works correct with paths that contains only base name like
aa
andaa/
- It works correct with paths starting with
/
and the path/
itself. - It works correct with any
$str
if it contains\n
at the end or not, even with many\n
- It uses cross platform sed command
- It changes all combinations of
/
(//
///
) to/
- It can't work correct with paths containing newlines and characters invalid for current locale.
- 它与尾随工作正常
/
- 它适用于仅包含基本名称的路径,例如
aa
和aa/
- 它适用于以开头
/
的路径和路径/
本身。 - 无论
$str
是否包含\n
在末尾,它都可以正常工作,即使有很多\n
- 它使用跨平台 sed 命令
- 它将
/
(//
///
) 的所有组合更改为/
- 对于包含对当前语言环境无效的换行符和字符的路径,它无法正常工作。
NoteAlternative for basename
may be useful:
注意替代 forbasename
可能有用: