OK. Doing exactly what you're requesting, I have an example that uses sed and ex. If you only need to delete lines that contain the digit string between [
and ]
after finding lan5:5
, I also have an awk example that does that. The following script includes both of these examples. Hopefully, one or both of these will do what you want:
#!/bin/ksh
# Usage: tester file pattern
# For the example given in this thread, file is the name of the input file and
# pattern is lan5:5.
if [ $# -ne 2 ] || ! cp $1 backup$$
then printf "Usage: %s file pattern\n" ${0##*/} >&2
exit 1
fi
# Gather operands:
file="$1"
pattern="$2"
printf "A backup copy of \"%s\" has been saved as \"%s\"\n" "$file" backup$$
# Try 1st example using sed to create a pattern to match and ex to remove lines
# containing that pattern.
echo 'using sed and ex:'
# Set RE to a BRE that will match "[digits]" where digits is the value found on
# the line that contains the given pattern inside double quotes, and print that
# BRE for reference..
RE="$(sed -n "s/.*[[]\\([0-9]*\\)[]].*\"$pattern\".*/[[]\\1[]]/p" "$file")"
printf "RE is \"%s\"\n" "$RE"
# Use ex to delete every line from file that matches the computed RE and check
# the exit status:
if ex -s "$file" <<-EOF
:g/$RE/d
:wq
EOF
then # ex complted successfully, verify that we got the expected results:
if diff "$file" expected
then echo 'Succeeded'
fi
else echo 'ex or sed error or no match found'
fi
# Print the updated file:
cat "$file"
# Now try 2nd example using awk:
echo
echo 'using awk:'
# Restore the given file to its original contents
cp backup$$ "$file"
if awk -v pat="\"$pattern\"" '
$0 ~ pat {
# We found a line that contains the given pattern inside double quotes.
if(match($0, /[[][0-9]+[]]/)) {
# And we found a digit string between "[" an "]", create a
# pattern to match that digit string and the "[" before it and
# the "]" after it
RE = "[[]" substr($0, RSTART + 1, RLENGTH - 2) "[]]"
# Note that we have found the pattern and created an ERE to
# match the correponding digit string in square brackets:
found = 1 # Note that we have found the pattern and
# created an ERE to match the digit string.
}
}
!found || $0 !~ RE # print the current line if we have not found the
# pattern or have found the pattern but this line does
# not match the ERE.
END { exit !found # Set exit status: 0->success, 1->pattern not found
}' "$file" > _tmp$$
then # awk completed successfully, cp results back to the input file and
# remove the temp file:
cp _tmp$$ "$file"
rm _tmp$$
else echo "awk failed or no match found"
fi
# Verify that we got what we expected:
if diff "$file" expected
then # Success, print the updated file.
echo 'Succeeded'
cat "$file"
fi
if [ -f _tmp$$ ]
then # awk failed, print the contents of our temp file:
echo _tmp$$
cat "_tmp$$"
fi
I use the Korn shell, but this will also work with bash or any other POSIX conforming shell. If you are using a Solaris/SunOS system, use /usr/xpg4/bin/awk
, /usr/xpg6/bin/awk
, or nawk
instead of awk
.
If you save the above script in a file named tester
, make it executable by running the command:
chmod +x tester
and then run the command:
./tester file "lan5:5"
(assuming that the input file you showed us in message #1 in this thread is stored in a file named file
and the expected output shown in that message is stored in a file named expected
), the output produced will be something like:
A backup copy of "file" has been saved as "backup94188"
using sed and ex:
RE is "[[]8[]]"
Succeeded
BROADCAST_ADDRESS[5]="10.140.236.255"
INTERFACE_STATE[5]="up"
DHCP_ENABLE[5]="0"
INTERFACE_MODULES[5]=""
ROUTE_DESTINATION[2]=default
ROUTE_GATEWAY[2]=10.40.118.4
ROUTE_COUNT[2]=1
INTERFACE_NAME[10]="lan5:7"
IP_ADDRESS[10]="10.140.239.62"
SUBNET_MASK[10]="255.255.255.0"
BROADCAST_ADDRESS[10]="10.140.239.255"
INTERFACE_STATE[10]="up"
DHCP_ENABLE[10]="0"
using awk:
Succeeded
BROADCAST_ADDRESS[5]="10.140.236.255"
INTERFACE_STATE[5]="up"
DHCP_ENABLE[5]="0"
INTERFACE_MODULES[5]=""
ROUTE_DESTINATION[2]=default
ROUTE_GATEWAY[2]=10.40.118.4
ROUTE_COUNT[2]=1
INTERFACE_NAME[10]="lan5:7"
IP_ADDRESS[10]="10.140.239.62"
SUBNET_MASK[10]="255.255.255.0"
BROADCAST_ADDRESS[10]="10.140.239.255"
INTERFACE_STATE[10]="up"
DHCP_ENABLE[10]="0"
The number after "backup" in the output shown above in orange, is the process ID of the shell running this script.
If you then copy the backup file created by this script back to your input file and run it again with something like:
./tester file "lan5:x"
it will display error messages indicating that it couldn't find lan5:x
, show the updated input file produced by sed and ex, show the diffs between what awk script produced and what you wanted, and show the temp file created by awk.
If everything works as expected, remove the backup file after you have verified that your input file has been updated to contain what you wanted.
If the awk script fails, it may also leave around a file named _tmpdigits
where digits is also the process ID of the shell running this script. If it was an actual awk error (instead of not finding the given pattern in your input file), this temp file may help you debug what went wrong.
I hope the comments in the script explain what is going on, but if part of it doesn't make sense, feel free to ask for an explanation of the parts you don't understand.
Hope this helps...