我在shell编程中完全迷失了,主要是因为我使用的每个站点都提供了不同的工具来进行模式匹配。所以我的问题是使用什么工具在管道流中进行简单模式匹配。匹配文本引号(新手)
上下文:我有named.conf文件,我需要在一个简单文件中的所有区域名称作进一步处理。所以我做〜$ cat named.local | grep区,并在这里完全失去。我的输出是〜百个左右的换行符,形式为“zone”domain.tld“{”,我需要双引号文本。
感谢您展示一种方法来做到这一点。
Ĵ
我在shell编程中完全迷失了,主要是因为我使用的每个站点都提供了不同的工具来进行模式匹配。所以我的问题是使用什么工具在管道流中进行简单模式匹配。匹配文本引号(新手)
上下文:我有named.conf文件,我需要在一个简单文件中的所有区域名称作进一步处理。所以我做〜$ cat named.local | grep区,并在这里完全失去。我的输出是〜百个左右的换行符,形式为“zone”domain.tld“{”,我需要双引号文本。
感谢您展示一种方法来做到这一点。
Ĵ
我想你要找的是sed
...这是一个小号 tream 版 itor这将让你在一行接一行的基础上做的替代品。
正如你解释它,命令`cat named.local | grep的区域”给你一个输出有点像这样:
zone "domain1.tld" {
zone "domain2.tld" {
zone "domain3.tld" {
zone "domain4.tld" {
我猜你所要的输出是这样的,因为你说你需要用双引号的文本:
"domain1.tld"
"domain2.tld"
"domain3.tld"
"domain4.tld"
所以,在现实中,我们只是希望每行都包含双引号(包括双引号本身)之间的文本。
我不确定您是否熟悉Regular Expressions,但它们是一个非常宝贵的工具任何人编写shell脚本。例如,正则表达式/.o.e/
可以匹配任何行,其中第二个字母为小写字母o
,第四个字母为e
。这将匹配包含字符串的话,如“zone
”,“tone
”,甚至“I am tone-deaf.
”
的有使用.
(点)字符伎俩来表示“任意字母”。还有一些其他特殊字符,如*
,意思是“重复上一个字符0次或更多次”。因此,像a*
正则表达式将匹配“a
”,“aaaaaaa
”,或一个空字符串:“”
所以,你可以使用匹配的引号内的字符串:/".*"/
有,你会知道的另一件事sed
(通过评论,你已经做到了!) - 它允许回溯。一旦你告诉它如何识别一个单词,你可以让它使用这个单词作为替换的一部分。例如,假设你希望把这个名单:
Billy "The Kid" Smith
Jimmy "The Fish" Stuart
Chuck "The Man" Norris
进入这个名单:
The Kid
The Fish
The Man
首先,你会寻找引号内的字符串。我们已经看到,这是/".*"/
。
接下来,我们要使用引号内的内容。我们可以组它使用括号:/"(.*)"/
如果我们想替换用下划线引号的文本,我们会做一个替换:s/"(.*)"/_/
,这将留给我们:
Billy _ Smith
Jimmy _ Stuart
Chuck _ Norris
但是我们有回溯!这会让我们回想起那些包裹里面的东西,使用符号\1
。所以,如果我们现在做的:s/"(.*)"/\1/
我们会得到:
Billy The Kid Smith
Jimmy The Fish Stuart
Chuck The Man Norris
因为没有引号的话在括号,他们不是的\1
部分内容!
只留下双引号内的内容,我们需要匹配整行。 (意思是“行结束”),为了做到这一点,我们有^
(意思是“行首”),并$
因此,如果我们用s/^.*"(.*)".*$/\1/
,我们会得到:
The Kid
The Fish
The Man
为什么?让我们由左到右阅读正则表达式s/^.*"(.*)".*$/\1/
:
s/
- 启动替代正则表达式^
- 寻找该行的开始。从那里开始。.*
- 继续阅读每个字符,直到..."
- ...直到您达到双引号。(
- 开始一组我们可能想在回溯后回想的角色。.*
- 继续下去,阅读每一个字符,直到...)
- (!pssst关闭组)"
- ...直到你到达一个双引号。.*
- 继续下去,阅读每一个字符,直到...$
- 行的结束!
/
- 使用后,这是什么来代替你匹配
\1
- 粘贴相匹配的第一组(什么是在括号)的内容。/
- 正则表达式在纯英文的结束:“读整条生产线,复制抛开双引号之间的文本,然后替换为双qoutes之间的内容整条生产线。“
您甚至可以添加双引号周围的替换文本s/^.*"(.*)".*$/"\1"/
,所以我们会得到:
"The Kid"
"The Fish"
"The Man"
并能由sed
用于替换从引号内内容的行:
sed -e "s/^.*\"\(.*\)\".*$/\"\1\"/"
(这只是壳逃出来处理双引号和斜线之类的东西。)
所以整个命令WO可能是这样的:
cat named.local | grep zone | sed -e "s/^.*\"\(.*\)\".*$/\"\1\"/"
你应该看看awk。
1.
[email protected]:etc$ cat named.conf | grep zone
zone "." IN {
zone "localhost" IN {
file "localhost.zone";
zone "0.0.127.in-addr.arpa" IN {
2.
[email protected]:etc$ cat named.conf | grep ^zone
zone "." IN {
zone "localhost" IN {
zone "0.0.127.in-addr.arpa" IN {
3.
[email protected]:etc$ cat named.conf | grep ^zone | sed 's/.*"\([^"]*\)".*/\1/'
.
localhost
0.0.127.in-addr.arpa
的正则表达式是.*"\([^"]*\)".*
,它匹配:
.*
"
\(
[^"]*
\)
"
.*
当调用sed
,语法是's/what_to_match/what_to_replace_it_with/'
。单引号是为了让您的正则表达式不会被bash
扩大。当你使用parens“记住”正则表达式中的某些东西时,可以将它记忆为\1
,\2
等。用它来捣鼓一段时间。
嘛,没有人提到cut
还,所以,证明有很多方法可以做一些与外壳:
% grep '^zone' /etc/bind/named.conf | cut -d' ' -f2
"gennic.net"
"generic-nic.net"
"dyn.generic-nic.net"
"langtag.net"
只要有人指出SED/AWK,我要去指出grep是多余的。
sed -ne '/^zone/{s/.*"\([^"]*\)".*/\1/;p}' /etc/bind/named.conf
这给你没有引号的内容(把括号内的引号保留下来)。在awk中,引用更简单:
awk '/^zone/{print $2}' /etc/bind/named.conf
我尽量避免使用管道(但不是更多)。请记住,Don't pipe cat。这不是必需的。而且,如awk和sed复制grep的工作,请不要grep。至少,不是sed或awk。
就我个人而言,我可能会用perl。但是那是因为我可能会在perl中完成所有其他的工作,使其成为一个小细节(并且能够同时处理所有文件和正则表达式,而忽略\ n对于哪些情况会是一种奖励。我不控制/ etc/bind,比如在一个共享的虚拟主机上)。但是,如果我是用壳做的话,上面两个中的一个就是我接近它的方式。
是的,我现在使用它,但我认为应该有更简单的方法来做到这一点,因为现在我使用sed -e's/zone“// g'| sed -e's /”{ // g'删除文件的开头和结尾,而不是仅仅匹配中间。 – jpou 2009-04-27 07:23:29