需要帮助扫描文本文件并找到两种模式之间的所有单词。就像说如果我们有一个.sql文件,需要扫描并找到'和'之间的所有单词'。 Grep一次只能扫描1行。对于此要求,最好使用的unix脚本是什么? sed,awk有这些功能吗?非常感谢指出任何例子。
答案 0 :(得分:22)
Sed有这个:
sed -n -e '/from/,/where/ p' file.sql
打印带有from
的行和带有where
的行之间的所有行。
对于包含同时包含from和where的行的内容:
#!/bin/sed -nf
/from.*where/ {
s/.*\(from.*where\).*/\1/p
d
}
/from/ {
: next
N
/where/ {
s/^[^\n]*\(from.*where\)[^\n]*/\1/p
d
}
$! b next
}
这(作为sed脚本编写)稍微复杂一些,我将尝试解释详细信息。
第一行是在包含from
和where
的行上执行的。如果一行与该模式匹配,则执行两个命令。我们使用s
替换命令仅提取from和where之间的部分(包括from和where)。该命令中的p
后缀打印该行。 delete命令清除模式空间(工作缓冲区),加载下一行并重新启动脚本。
当找到包含from
的行时,第二个命令开始执行一系列命令(按大括号分组)。基本上,这些命令形成一个循环,该循环将保持从输入到模式空间的附加行,直到找到具有where
的行或直到我们到达最后一行。
:
“命令”在脚本中创建一个标签,一个标记,允许我们在需要时“跳回”。 N
命令从输入中读取一行,并将其附加到模式空间(用换行符分隔行)。
当找到where
时,我们可以打印出模式空间的内容,但首先我们必须用substitute命令清除它。它类似于之前使用的那个,但我们现在用.*
替换前导和尾随[^\n]*
,它告诉sed只匹配非换行符,有效地匹配第一行中的from和在最后一行的位置。然后d
命令清除模式空间并在下一行重新启动脚本。
b
命令将跳转到标签,在我们的示例中为标签next
。但是,$!
地址表示不应该在最后一行执行,允许我们离开循环。当我以这种方式离开循环时,我们没有找到相应的where
,因此您可能不想打印它。
但请注意,这有一些缺点。以下情况不会按预期处理:
from ... where ... from
from ... from
where
from
where ... where
from
from
where
where
处理这些案件需要更多代码。
希望这有助于=)
答案 1 :(得分:2)
使用GNU awk,您可以将RS设置为RE:
gawk -v RS='[[:space:]]+' '
/where/ { found=0 }
found { print }
/from/ { found=1 }
' file
以上假设您不希望打印“from”和“where”,如有必要,可以移动线条。
如果有帮助,以下习语描述了如何选择给定的记录范围 要匹配的特定模式:
a)打印某些模式的所有记录:
awk '/pattern/{f=1}f' file
b)在某种模式之后打印所有记录:
awk 'f;/pattern/{f=1}' file
c)在某种模式后打印第N条记录:
awk 'c&&!--c;/pattern/{c=N}' file
d)在某种模式之后打印除第N条记录以外的所有记录:
awk 'c&&!--c{next}/pattern/{c=N}1' file
e)在某种模式之后打印N条记录:
awk 'c&&c--;/pattern/{c=N}' file
f)在某种模式之后打印除N条记录之外的所有记录:
awk 'c&&c--{next}/pattern/{c=N}1' file
g)从某种模式打印N条记录:
awk '/pattern/{c=N}c&&c--' file
我将变量名称从“f”更改为“found”到“c”更改为“count” 适当的,因为它更能表达变量实际上是什么。
答案 2 :(得分:1)
您可以使用ed
,它允许正则表达式范围的正负偏移。如果输入是:
seq 10 | tee > infile
1
2
3
4
5
6
7
8
9
10
将命令传递给ed
:
<<< /3/,/6/p | ed -s infile
即。在包含3
和6
的行之间打印所有内容。
结果:
3
4
5
6
要在每一端增加一条线:
<<< /3/-1,/5/+1p | ed -s infile
结果:
2
3
4
5
6
7
或者相反:
<<< /3/+1,/6/-1p | ed -s infile
结果:
4
5
答案 3 :(得分:1)
我只用grep:
完成了这个#> grep -A#### "start pattern" file | grep -B#### "end pattern"
问题在于我必须找到包含在A和B选项中的正确数量的行,这些行是相同的。 希望这有帮助
答案 4 :(得分:0)
要返回两个给定字符串中的一个字符串,沿着awk
的行(不要发疯)我只是运行这个非常扁平的脚本,详细说明:
.\gnucoreutils\bin\awk "{startstring = \"RETURN STUFF AFTER ME \"; endstring = \"RETURN STUFF BEFORE ME\"; endofstartstring = index($0,startstring)+length(startstring); print substr($0,endofstartstring,index($0,endstring)-endofstartstring)}" /dev/stdin
请注意,我使用cmd.exe
(Windows命令解释程序)和the gnuwin32 awk,所以请注意“双引号”和^ \转义字符^ \:
GNU Awk 3.1.6
Copyright (C) 1989, 1991-2007 Free Software Foundation.
请指出缺陷。
示例:
echo "hello. RETURN STUFF AFTER ME i get returned RETURN STUFF BEFORE ME my face is melting" | .\gnucoreutils\bin\awk "{startstring = \"RETURN STUFF AFTER ME \"; endstring = \" RETURN STUFF BEFORE ME\"; endofstartstring = index($0,startstring)+length(startstring); print substr($0,endofstartstring,index($0,endstring)-endofstartstring)}" /dev/stdin
i get returned