I\'m getting totally lost in shell programming, mainly because every site I use offers different tool to do pattern matching. So my question is what tool to use to do simple pat
I think what you're looking for is sed
... it's a stream editor which will let you do replacements on a line-by-line basis.
As you're explaining it, the command `cat named.local | grep zone' gives you an output a little like this:
zone "domain1.tld" {
zone "domain2.tld" {
zone "domain3.tld" {
zone "domain4.tld" {
I'm guessing you want the output to be something like this, since you said you need the text in double quotes:
"domain1.tld"
"domain2.tld"
"domain3.tld"
"domain4.tld"
So, in reality, from each line we just want the text between the double-quotes (including the double-quotes themselves.)
I'm not sure you're familiar with Regular Expressions, but they are an invaluable tool for any person writing shell scripts. For example, the regular expression /.o.e/
would match any line where there's a word with the 2nd letter was a lower-case o
, and the 4th was e
. This would match string containing words like "zone
", "tone
", or even "I am tone-deaf.
"
The trick there was to use the .
(dot) character to mean "any letter". There's a couple of other special characters, such as *
which means "repeat the previous character 0 or more times". Thus a regular expression like a*
would match "a
", "aaaaaaa
", or an empty string: ""
So you can match the string inside the quotes using: /".*"/
There's another thing you would know about sed
(and by the comments, you already do!) - it allows backtracking. Once you've told it how to recognize a word, you can have it use that word as part of the replacement. For example, let's say that you wanted to turn this list:
Billy "The Kid" Smith
Jimmy "The Fish" Stuart
Chuck "The Man" Norris
Into this list:
The Kid
The Fish
The Man
First, you'd look for the string inside the quotes. We already saw that, it was /".*"/
.
Next, we want to use what's inside the quotes. We can group it using parens: /"(.*)"/
If we wanted to replace the text with the quotes with an underscore, we'd do a replace: s/"(.*)"/_/
, and that would leave us with:
Billy _ Smith
Jimmy _ Stuart
Chuck _ Norris
But we have backtracking! That'll let us recall what was inside the parens, using the symbol \1
. So if we do now: s/"(.*)"/\1/
we'll get:
Billy The Kid Smith
Jimmy The Fish Stuart
Chuck The Man Norris
Because the quotes weren't in the parens, they weren't part of the contents of \1
!
To only leave the stuff inside the double-quotes, we need to match the entire line. To do that we have ^
(which means "beginning of line"), and $
(which means "end of line".)
So now if we use s/^.*"(.*)".*$/\1/
, we'll get:
The Kid
The Fish
The Man
Why? Let's read the regular expression s/^.*"(.*)".*$/\1/
from left-to-right:
s/
- Start a substitution regular expression^
- Look for the beginning of the line. Start from there..*
- Keep going, reading every character, until..."
- ... until you reach a double-quote.(
- start a group a characters we might want to recall later when backtracking..*
- Keep going, reading every character, until...)
- (pssst! close the group!)"
- ... until you reach a double-quote..*
- Keep going, reading every character, until...$
- The end of the line!
/
- use what's after this to replace what you matched
\1
- paste the contents of the first group (what was in the parens) matched./
- end of regular expressionIn plain English: "Read the entire line, copying aside the text between the double-quotes. Then replace the entire line with the content between the double qoutes."
You can even add double-quote around the replacing text s/^.*"(.*)".*$/"\1"/
, so we'll get:
"The Kid"
"The Fish"
"The Man"
And that can be used by sed
to replace the line with the content from within the quotes:
sed -e "s/^.*\"\(.*\)\".*$/\"\1\"/"
(This is just shell-escaped to deal with the double-quotes and slashes and stuff.)
So the whole command would be something like:
cat named.local | grep zone | sed -e "s/^.*\"\(.*\)\".*$/\"\1\"/"