Select lines between two patterns using variables inside SED command

时间:2017-07-20 16:41:30

标签: linux bash shell awk sed

I'm new to shell scripting. My requirement is to retrieve lines between two pattern, its working fine if I run it from the terminal without using variables inside sed cmd. But the problem arises when I put all those below cmd in a file and tried to execute it.

#!/bin/sh
word="ajp-qdcls2228.us.qdx.com%2F156.30.35.204-8009-34"
upto="2017-01-03 23:00"
fileC=`cat test.log`
output=`echo $fileC | sed -e "n/\$word/$upto/p"`
printf '%s\n' "$output"

If I use the below cmd in the terminal it works fine

sed -n '/ajp-qdcls2228.us.qdx.com%2F156.30.35.204-8009-34/,/2017-01-03 23:00/ p' test.log

Please suggest a workaround.

2 个答案:

答案 0 :(得分:2)

如果我们搁置一下这个事实你不应该cat一个文件到一个变量,然后echo它用于sed过滤,你的命令是不工作是因为fileC时你没有引用文件内容变量echo。这将把多个空格字符组合在一起并将它们转换为单个空格。因此,您从文件中丢失新行,以及多个空格,标签等。

要修复它,你可以写:

fileC=$(cat test.log)
output=$(echo "$fileC" | sed -n "/$word/,/$upto/p")

请注意fileC周围的双引号(以及固定的sed表达式,类似于第二个示例)。如果没有引号(尝试echo $fileC),您的fileC会被扩展(使用默认的IFS)成一系列单词,每个单词都是echo的一个参数,而{echo 1}}只会打印用单个空格分隔的单词。此外,如果文件包含一些通配符(如*),那么模式也会扩展。这是common bash pitfall

更好的来写这样:

output=$(sed -n "/$word/,/$upto/p" test.log)

如果您的模式包含一些sed元字符,那么在使用sed之前,您应该escape them,如下所示:

escape() {
    sed 's/[^^]/[&]/g; s/\^/\\^/g' <<<"$1";
}
output=$(sed -n "/$(escape "$word")/,/$(escape "$upto")/ p" test.log)

答案 1 :(得分:1)

正确的方法将是:

word="ajp-qdcls2228.us.qdx.com%2F156.30.35.204-8009-34"
upto="2017-01-03 23:00"
awk -v beg="$word" -v end="$upto" '$0==beg{f=1} f{print; if ($0==end) exit}' file

但在我们看到您的示例输入和输出之前,我们无法确定您需要匹配的内容(全行,部分行,一行中的所有文本等)或您想要的内容print(包括分隔符,排除一个,排除两者等)。