使用grep,将两行视为一行?

时间:2012-10-08 05:28:40

标签: linux bash grep

假设我有一个配置文件,可以采用以下两种格式之一(简短示例,但基本上第一种格式是一条太长的行,您必须使用行继续符,而第二种格式只是只是一条没有延续线的长线)

data1=x data2=y data3=z \
datakey

第二种格式

data=1 data2=y data3=z datakey

我希望在两种情况下都匹配确切的行data1=x data2=y data3=x datakey。有没有简单的方法呢?

5 个答案:

答案 0 :(得分:4)

read\解释为行继续符:

while read line ; do
    if [[ $line == 'data=1 data2=y data3=z datakey' ]] ; then
        echo "$line"
    fi
done

答案 1 :(得分:1)

也许grep不是解决这类问题的最佳工具。

您可以使用\加入所有行结尾,然后照常输出grep:

假设您有一个文件:

$> cat text
1
2
fasdfasdf
data1=x data2=y data3=z \
datakey
fasfd
sdf

因此,您可以使用\加入所有行结尾:

$> awk '{line = $0}; /.*\\/ {split($0,tmp,"\\"); line = tmp[1]; getline; line = line $0}; { print line }' text
1
2
fasdfasdf
data1=x data2=y data3=z datakey
fasfd
sdf

答案 2 :(得分:1)

我会使用sed创建一个没有结尾\的输出:

sed -e ':begin;/\\$/{N;bbegin};s/\\\n//g' your_file

然后你可以grep它:

sed -e ':begin;/\\$/{N;bbegin};s/\\\n//g' your_file | grep your_pattern

你甚至可以在sed中完成所有这些:

sed -n -e ':begin;/\\$/{N;bbegin};s/\\\n//g;/your_pattern/p' your_file

<强>更新

上面解释:

  • :begin使用b命令设置我可以分支(转到)的标记。
  • /\\$/{N;bbegin}如果当前行以\/\\$/)结尾,则将下一行追加到缓冲区(N)并转到开头(bbegin })。
  • 然后,当这些行没有以\结尾时,请删除所有\和换行符(the s / \\ n // g`)。
  • 然后-n选项告诉sed no在脚本末尾打印行。
  • /your_pattern/p如果匹配your_pattern,则会打印该行。

<强> UPDATE2

我们甚至可以做得更好并显示文件的原始行:

sed -n -e ':begin;/\\$/{N;bbegin};h;s/\\\n//g;/your_pattern/{g;p}' your_file

这样做是在删除\和换行符之前,它将数据保存在保留空间(h)中,如果行匹配,则会打印保存的数据({ {1}}将保留空间复制到打印的图案空间。

答案 3 :(得分:0)

awk -v i="data1=x data2=y data3=z datakey" '{x=x" "$0}END{y=match(x," "i);if(y) print "yes its a match"}' temp

测试如下:

> cat temp
data1=x data2=y data3=z
datakey
> awk -v i="data1=x data2=y data3=z datakey" '{x=x" "$0}END{y=match(x," "i);if(y) print "yes its a match"}' temp
yes its a match
> 

答案 4 :(得分:0)

我喜欢上面的sed示例,并且没有注意到awk的例子 提交。这是awk(nawk)版本,保持格式和交易 具有多个连续行和文件结尾。

nawk -v re="search-string" \
'{ls=ls""$0;lp=lp""$0}
/\\$/{ls=substr(ls,1,length(ls)-1);lp=lp"\n";next}
ls~re{print lp}
{lp=ls=""}
END{if (ls ~ re)print substr(lp,1,length(lp)-1)}' input-file

说明:

  1. re = search-string 设置要查找的正则表达式。
  2. ls = ls“”$ 0 将新行连接到ls(行搜索),也存储 原始行到lp(行打印),如上面的例子所示。
  3. / \\ $ / 检查输入是否具有连续字符和 如果它确实substr()从ls中删除了额外的字符,那么lp有一个 附加换行符以保留原始格式。最后下一步 导致awk读取下一行并从第一条规则开始。
  4. ls~i 搜索line-search re,如果匹配print lp , 可以添加一个开关来打印 ls ,如果愿意的话。
  5. 最后(不倒数第二)重置ls&amp; lp没有延续线时。
  6. END是特殊规则,用于检测 ls 是否还有 赋值,意味着延续线位于EOF。搜索正则表达式,当它 匹配它会切断上面添加的额外换行符。
  7. 现在,没有人会在一行的末尾写'\'吗?