2011-12-19 180 views
5

我想这条线使用绝对路径提取目录名awk或者sed

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

拆分使用sedawk脚本

/home/edwprod/abortive_visit/bin 

?你能帮忙吗?

+0

什么是上下文?这是在一个文件?你有多次发生?你做... ? – fge 2011-12-19 10:58:57

+1

sed和awk对此过度杀伤,shell直接为此提供了实用程序。 – Mat 2011-12-19 11:01:51

+1

如果你使用bash:为什么不使用'dirname'命令? – codeling 2011-12-19 11:02:04

回答

5

可能是命令dirname是你在寻找什么?

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

或者,如果你想SED,所以看到我的解决方案:

echo /home/edwprod/abortive_visit/bin/abortive_proc_call.ksh | sed 's/\(.*\)\/.*/\1/' 
+1

“基于sed”的解决方案存在仅包含基本名称的路径问题。在这种情况下'dirname'返回'.'。 – 2016-04-18 10:20:33

11

目录名

kent$ dirname "/home/edwprod/abortive_visit/bin/abortive_proc_call.ksh" 
/home/edwprod/abortive_visit/bin 

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

kent$ echo "/home/edwprod/abortive_visit/bin/abortive_proc_call.ksh"|awk -F'/[^/]*$' '{print $1}' 
/home/edwprod/abortive_visit/bin 
+1

在“dirname”的所有这些替代方法中,仅包含基本名称的路径存在问题。 'dirname'在这种情况下给出'.'。 'grep'版本返回一个空字符串,其他的则作为'basename' – 2016-04-18 10:18:50

1

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}' 
0

对于大多数平台和Unix/Linux外壳现已dirname

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

使用的dirname是simpliest方式,但不推荐用于例如最后的跨平台脚​​本版本autoconf文档http://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Limitations-of-Usual-Tools.html#Limitations-of-Usual-Tools

所以sed基替代的dirname我的全功能版本:

str="/home/edwprod/abortive_visit/bin/abortive_proc_call.ksh" 
echo "$str" | sed -n -e '1p' | sed -e 's#//*#/#g' -e 's#\(.\)/$#\1#' -e 's#^[^/]*$#.#' -e 's#\(.\)/[^/]*$#\1#' - 

例子:

它的工作原理就像dirname

  • 对于像/aa/bb/cc路径,它将打印/aa/bb
  • 对于像/aa/bb这样的路径,它将打印/aa
  • 对于像/aa/bb/这样的路径,它也会打印/aa
  • 对于像/aa/路径,它将打印/aa
  • 对于像/路径,它将打印/
  • 对于像aa路径,它将打印.
  • 对于像aa/路径,它将打印.

即:

  • 它与尾随/
  • 它的工作原理与正确包含像aaaa/
  • 它与开始/路径和路径/本身只有正确基本名称的路径是正确的。
  • 它适用于任何$str正确的,如果它包含\n在年底或没有,甚至有许多\n
  • 它采用跨平台的sed命令
  • 它改变了//////)的所有组合/
  • 它无法正确处理当前语言环境中包含换行符和字符无效的路径。

注意 替代计划basename可能是有用的:

echo "$str" | awk -F"/" '{print $NF}' - 
0

此代码与AWK将工作完全是一样目录名,我猜。

它非常简单,工作成本非常低。祝你好运。

代码

$ foo=/app/java/jdk1.7.0_71/bin/java 
$ echo "$foo" | awk -F "/?[^/]*/?$" ' 
{ print ($1 == "" ? (substr($0, 1, 1) == "/" ? "/" : ".") : $1); }' 

结果

/app/java/jdk1.7.0_71/bin

测试

  • 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/ - >.

如果你不提供此类AWK分隔符,尝试这种方式。

$ echo $foo | awk '{ 
dirname = gensub("/?[^/]*/?$", "", "", $0); 
print (dirname == "" ? (substr($0, 1, 1) == "/" ? "/" : ".") : dirname); 
}'