从ps的输出中提取基目录

时间:2014-04-30 16:12:16

标签: regex bash awk sed grep

我希望从ps -ef | grep classpath myprog.jar

的输出中提取一个basedir
root  20925 20886  1 17:41 pts/0  00:01:07 /opt/myprog/java/jre/bin -classpath myprog.jar

java始终是basedir 下的子目录,但安装路径因服务器而异,例如

/usr/local/myprog/java/jre/bin

/opt/test/testing/myprog/java/jre/bin

所以,一旦我拥有了我的字符串,我如何从之前 java 中提取所有内容,直到路径的开头?

/usr/local/myprog/opt/test/testing/myprog/

6 个答案:

答案 0 :(得分:1)

使用sed:

$ echo "root  20925 20886  1 17:41 pts/0  00:01:07 /opt/myprog/java/jre/bin -classpath myprog.jar" | sed 's/.*\ \(.*\)\/java.*/\1/'
/opt/myprog

答案 1 :(得分:0)

使用grep -P

ps -ef | grep -oP '\S+(?=/java)'
/opt/myprog

如果您的grep不支持-P,请使用:

s='root  20925 20886  1 17:41 pts/0  00:01:07 /opt/myprog/java/jre/bin -classpath myprog.jar'
[[ "$s" =~ (/[^[:blank:]]+)/java ]] && echo "${BASH_REMATCH[1]}"
/opt/myprog

答案 2 :(得分:0)

echo "root  20925 20886  1 17:41 pts/0  00:01:07 /opt/myprog/java/jre/bin -classpath myprog.jar" | awk '{split($8,a,"/java"); print a[1]}'

答案 3 :(得分:0)

使用pgrep查找所有Java进程,而不是使用ps -ef | grep ...。这样,您就不必担心grep命令会显示为您的某个项目。

您可以使用ps -ef选项仅提取所需字段,而不是运行-o,而大多数ps命令会使用--no-header来删除标题字段。这样,您的脚本就不必担心标题行了。

最后,我使用Shell Parameter Expansion,这有时比使用sed更改变量更容易:

$ ps -o pid,args --no-headers $(pgrep -f "java .* myproj.jar") | while read pid command arguments
do
    directory=${command%/java*}
    echo "The directory for Process ID $pid is $directory"
done

顺便说一句,您可能正在运行多个命令,因此我遍历ps命令。

答案 4 :(得分:0)

ps axo args | awk '/classpath myprog.jar/{print substr($0, 0,index($0, "java")-1)}'

例如:

$ echo '/opt/myprog/java/jre/bin -classpath myprog.jar' \
  | awk '/classpath myprog.jar/{print substr($0, 0,index($0, "java")-1)}'
/opt/myprog/

如果您确定自己的路径不包含空格,则可以(并且可能应该)将$0转换为$1' s。或者使用逗号将其他字段添加到ps -o列表中(例如,o pid,args)并使用$2而不是$1

答案 5 :(得分:-1)

您可以匹配以下正则表达式:

'((\/\w+)+)\/java'

并且第一个捕获的组\1$1将包含所需的字符串

演示:http://regex101.com/r/zU2vV4