问题
I cant quite get my statements working as I need.
I need to find if each of the patterns called Group contain the line FUNEnable within a config file. If its present then add a line after it within the file, if not then print a warning to screen. The could be any number of patterns called group as shown below:
Sample file
#config file
<Some config>
More config
</Some config>
#comment about FUNEnable
Other config things
<Group small.group>
Something here
FUNEnable
Funfile /someplace/afunfile
</Group>
<Group medium.group>
More stuff here
Funfile /someplace/afunfile
</Group>
First attempt:
cat configfile.conf | awk '/^<Group/,/^<\/Group>/' | grep -q ^'FUNEnable' || print "WARNING";
This works great if both patterns do not have SSLEnable but if one has SSLEnable present then it does not print the warning. I obviously need to build some form of loop into it but not quite sure
cat configfile.conf | awk -F /\n '/^<Group/,/^<\/Group>/ { if ($1 == "FUNEnable") {print $1 "\nANOTHER LINE"} else { print "WARNING"}}';
This doesnt quite do what i need.
Any pointers would be great.
回答1:
$ awk '/^<Group/{name=$2;missing=1} /FUNEnable/{missing=0} /^<\/Group/ && missing {print "FUNEnable missing for group <" name}' configfile.conf
FUNEnable missing for group <medium.group>
How it works:
/^<Group/{name=$2;missing=1}Every time that a new group is started, initialize the variable
nameto the group name and the variablemissingto true (1)./FUNEnable/{missing=0}Everytime that we encounter
FUNEnableon a line, reset the variablemissingto false (0)./^<\/Group/ && missing {print "FUNEnable missing for group <" name}When we reach the end of a group and if
missingis true, then print a warning.
The above was tested with GNU awk.
回答2:
Quick and dirty one-liner for what sounds like a quick and dirty task:
gawk -vRS='<Group' '!/\nFUNEnable.*<\/Group>/ && sub(/<\/Group>.*/,"") {print RS $0}'
Most of what it does is break the input into records separated with <Group and then echo out records that don't contain the right regex. You need GNU Awk to set RS to a multichar string.
回答3:
Store some state in your awk script.
awk '
BEGIN{ingroup = 0; found = 0;}
/begingroup/{ingroup = 1;}
$0 ~ /pattern/ && ingroup == 1{found = 1;}
/endgroup/ {if(found == 0) print "Pattern not found in group";
found = 0; ingroup = 0;}'
In the above script, replace begingroup, pattern and endgroup with the corresponding regexes.
回答4:
This may work:
awk -F"\n" '{for (i=1;i<=NF;i++) if ($i~/^[ \t]*FUNEnable/) {f=1;$i=$i"\nNew line"}} 1; END {if (!f) print "not found"} ' RS="" OFS="\n" ORS="\n\n" configfile.conf
#config file
<Some config>
More config
</Some config>
#comment about FUNEnable
Other config things
<Group small.group>
Something here
FUNEnable
New line
Funfile /someplace/afunfile
</Group>
<Group medium.group>
More stuff here
Funfile /someplace/afunfile
</Group>
If it finds a line starting with FUNEnable it adds a new line after it.
If it's not found it prints not found at end of file.
Some more readable:
awk '
{
for (i=1;i<=NF;i++)
if ($i~/^[ \t]*FUNEnable/) {
f=1
$i=$i"\nNew line"}}
1
END {
if (!f) print "not found"}
' FS="\n" RS="" OFS="\n" ORS="\n\n" configfile.conf
来源:https://stackoverflow.com/questions/27475262/awk-find-if-specific-line-exists-between-multiple-common-patterns