匹配引号中的文字(新手)

jpo*_*pou 5 regex shell pattern-matching

我在shell编程中完全迷失了,主要是因为我使用的每个站点都提供了不同的工具来进行模式匹配.所以我的问题是用什么工具在管道流中进行简单的模式匹配.

context:我有named.conf文件,我需要一个简单文件中的所有区域名称进行进一步处理.所以我做〜$ cat named.local | grep区域并在这里完全丢失.我输出的形式为'zone"domain.tld"{'的约100个换行符,我需要双引号文本.

感谢您展示了这样做的方法.

Ĵ

Sha*_*mer 23

我想,你要寻找的是sed......这是一个小号 tream itor这将让你在一行接一行的基础上做的替代品.

正如您所解释的那样,命令`cat named.local | grep zone'给你一个像这样的输出:

zone "domain1.tld" {
zone "domain2.tld" {
zone "domain3.tld" {
zone "domain4.tld" {
Run Code Online (Sandbox Code Playgroud)

我猜你想要输出是这样的,因为你说你需要双引号文本:

"domain1.tld"
"domain2.tld"
"domain3.tld"
"domain4.tld"
Run Code Online (Sandbox Code Playgroud)

所以,实际上,从每一行我们只想要双引号之间的文本(包括双引号本身).

我不确定你是否熟悉正则表达式,但对于任何编写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
Run Code Online (Sandbox Code Playgroud)

进入这个列表:

The Kid
The Fish
The Man
Run Code Online (Sandbox Code Playgroud)

首先,你要在引号内查找字符串.我们已经看到了,它是/".*"/.

接下来,我们想要使用引号内的内容.我们可以使用parens对它进行分组:/"(.*)"/

如果我们想用引号替换带有下划线的文本,我们会做一个替换:s/"(.*)"/_/,这会让我们:

Billy _ Smith
Jimmy _ Stuart
Chuck _ Norris
Run Code Online (Sandbox Code Playgroud)

但我们有回溯!那将让我们回想一下使用符号的内部内容\1.所以如果我们现在这样做:s/"(.*)"/\1/我们会得到:

Billy The Kid Smith
Jimmy The Fish Stuart
Chuck The Man Norris
Run Code Online (Sandbox Code Playgroud)

因为引号不在parens中,所以它们不是内容的一部分\1!

要仅将内容留在双引号内,我们需要匹配整行.要做到这一点,我们有^(这意味着"行首")和$(这意味着"行尾".)

所以现在如果我们使用s/^.*"(.*)".*$/\1/,我们将获得:

The Kid
The Fish
The Man
Run Code Online (Sandbox Code Playgroud)

为什么?让我们s/^.*"(.*)".*$/\1/从左到右阅读正则表达式:

  • s/- 开始替换正则表达式
  • ^ - 寻找线的开头.从那里开始.
  • .* - 继续前进,阅读每一个角色,直到......
  • " - ...直到你达到双重报价.
  • ( - 开始一组我们可能想要在回溯时回忆的字符.
  • .* - 继续前进,阅读每一个角色,直到......
  • ) - (pssst!关闭小组!)
  • " - ...直到你达到双重报价.
  • .* - 继续前进,阅读每一个角色,直到......
  • $ - 结束了!

  • / - 使用之后的内容来替换您匹配的内容

  • \1 - 粘贴匹配的第一组(parens中的内容)的内容.
  • / - 正则表达式结束

用简单的英语:"读取整行,将文本复制到双引号之间.然后用双qoutes之间的内容替换整行."

你甚至可以在替换文本周围添加双引号s/^.*"(.*)".*$/"\1"/,这样我们就可以得到:

"The Kid"
"The Fish"
"The Man"
Run Code Online (Sandbox Code Playgroud)

这可以用来sed替换引号内的内容:

sed -e "s/^.*\"\(.*\)\".*$/\"\1\"/"
Run Code Online (Sandbox Code Playgroud)

(这只是shell转义处理双引号和斜线和东西.)

所以整个命令就像这样:

cat named.local | grep zone | sed -e "s/^.*\"\(.*\)\".*$/\"\1\"/"
Run Code Online (Sandbox Code Playgroud)