使用sed在两个斜杠之间提取字符串

时间:2018-01-11 15:50:18

标签: regex bash shell sed text-processing

我正在尝试使用sed从文件中的一行中提取特定字符串。目前我正在使用while循环读取文件并搜索特定字符串。当找到该字符串时,我正在解压缩它,但是我需要使用sed来解析输出,这样我才能获得两个斜杠之间的字符串(它是一个目录名,所以我需要保留起始斜杠和尾部斜杠,如果可能的话)。这是我正在运行的搜索文件的循环:

#!/bin/sh
file=configFile.conf
while read line 
do
    if  echo "$line" | grep -q "directory_root" 
    then DIR_ROOT="$line"
fi
done < "$file"
echo $DIR_ROOT
exit 0

while循环起作用并回显以下字符串:

directory_root /root/config/data/

然后我需要使用sed来获取以下输出,以便将正确的目录名称传递到另一个脚本:

/root/

是否可以使用sed和正则表达式从回显输出中仅提取上述内容?

由于

5 个答案:

答案 0 :(得分:3)

如果您想使用sed,则可以使用:

~/tmp> str="directory_root /root/config/data/"
~/tmp> echo $str | sed 's|^[^/]*\(/[^/]*/\).*$|\1|'
/root/

或单个衬垫(假设directory_root文字在行中:)

 cat file | sed -e 's|^directory_root \(/[^/]*/\).*$|\1|;tx;d;:x'

第一个例子中正则表达式的解释:

s|:使用|作为稀释剂(在这种情况下更容易阅读)

^:匹配行的开头

[^/]*:匹配所有非/个字符(这是贪婪的,所以它会在遇到第一个/时停止。

\(:开始录制字符串1

/:匹配文字/

[^/]*:匹配所有非/ charcaters

\):完成字符串1

.*:将所有其他内容匹配到行尾

|:分隔符

\1:将替换匹配为字符串1

|:分隔符

在第二个例子中,我附加了;tx;d;:x,它不回显与see here不匹配的行。然后,您可以在整个文件上运行它,它只会打印它修改的行。

~/tmp> echo "xx" > tmp.txt
~/tmp> echo "directory_root /root/config/data/" >> tmp.txt
~/tmp> echo "xxxx ttt" >> tmp.txt
~/tmp>
~/tmp> cat tmp.txt | sed -e 's|^directory_root \(/[^/]*/\).*$|\1|;tx;d;:x'
/root/

答案 1 :(得分:1)

您不一定需要sed。你可以使用bash:

#!/bin/bash

f="directory_root /asdf/asdfad/fad"
regex="^directory_root (\/\w+\/).*$"
if [[ $f =~ $regex ]]
then
    name="${BASH_REMATCH[1]}"
    echo $name
fi

打印/asdf/

请参阅:Capturing Groups From a Grep RegEx

答案 2 :(得分:1)

您可以使用两步变量替换将DIR_ROOT切割为top-dir:

DIR_ROOT="${DIR_ROOT#/}"    # cut away the leading slash
DIR_ROOT="/${DIR_ROOT%%/*}"  # cut the trailing path and re-add the slash

答案 3 :(得分:1)

由于您要求sed解决方案,我有一个适合您:

$ s="directory_root /root/config/data"
$ echo "${s}" | sed -e 's/\//\x00/; s/\//\x00/; s/.*\x00\(.*\)\x00.*/\/\1\//;'
/root/

这是如何工作的?好吧,因为sed没有非贪婪的匹配,诀窍是使用一系列搜索和替换来设置,这样你就不需要非贪婪。第一个s///NUL字节替换第一个斜杠,然后再次执行此操作。现在你将前两个斜杠(仅)替换为一个不会出现在任何UNIX shell字符串输入中的字节,所以现在你可以用常规,贪婪的方式提取\x00包围的目录。 sed搜索并替换(第三个s///)。

干杯!

注1:此解决方案部分受到an answer on unix stack exchange

的启发

注2:由于空字节,此解决方案需要GNU sed。如果您使用的是BSD sed(macos),您可能只想使用其他一些不会出现在输入中的分隔符。

PS:不使用sed可能更容易。

答案 4 :(得分:0)

sed -rn 's|^directory_root[[:blank:]]+(/[^/]*/?).*|\1|p' data
  • -n:禁止自动打印图案空间
  • -r:启用扩展正则表达式(无需转义+等)
  • s|regex|replacement|:您可以选择不同的分隔符
  • p:仅在regex匹配
  • 时打印当前模式空间
  • [:blank:]:匹配<tab><space>
  • ( regex ):捕获以后可以引用\1\2,...
  • 的群组

/[^/]*/?匹配/,后跟任意数量的非斜杠,可选地后跟另一个/。这将正确输出/root/

但是,如果您恰好拥有directory_root /directory_root /dir该怎么办?这就是/?的用途。如果您只想在目录被/包围的情况下打印目录,只需删除?