我正在尝试使用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和正则表达式从回显输出中仅提取上述内容?
由于
答案 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/
答案 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
该怎么办?这就是/?
的用途。如果您只想在目录被/
包围的情况下打印目录,只需删除?
。