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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 21:22:46  来源:igfitidea点击:

Extracting directory name from an absolute path using sed or awk

bashawksed

提问by AruM

I want to split this line

我想分割这条线

/home/edwprod/abortive_visit/bin/abortive_proc_call.ksh

to

/home/edwprod/abortive_visit/bin

using sedor awkscripts? Could you help on this?

使用sedawk脚本?你能帮忙吗?

采纳答案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:dirnameis 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 dirnameis the simpliest way, but it is not recommended for cross platform scripting for example in the last version of autoconfdocumentation 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/ccit will print /aa/bb
  • For path like /aa/bbit will print /aa
  • For path like /aa/bb/it will print /aatoo.
  • For path like /aa/it will print /aa
  • For path like /it will print /
  • For path like aait 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 aaand aa/
  • It works correct with paths starting with /and the path /itself.
  • It works correct with any $strif it contains \nat 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.
  • 它与尾随工作正常 /
  • 它适用于仅包含基本名称的路径,例如aaaa/
  • 它适用于以开头/的路径和路径/本身。
  • 无论$str是否包含\n在末尾,它都可以正常工作,即使有很多\n
  • 它使用跨平台 sed 命令
  • 它将/( /////) 的所有组合更改为/
  • 对于包含对当前语言环境无效的换行符和字符的路径,它无法正常工作。

NoteAlternative for basenamemay be useful:

注意替代 forbasename可能有用:

##代码##