I have a question related to deletion of strings that appear at the n+2 position after the matched string which is at position n using awk for multiple files. I am able to print it using the command:
awk -F '/radius-server/{nr[NR+4]}; NR in nr' *
Where the matched string is radius-server. Since I’m not too familiar with
awk I would appreciate it if someone could help me delete this line in place , that would mean that I want the files to be modified and saved after the deletion is done.
An example scenario is below –
file 1 which is unmodified
radius-server dz7HQQH4EqT5 1645-1646 ! oj5icqh1dGpSK ! alias exec t telnet alias exec sis show interface status !
file 2, after modification is –
radius-server dz7HQQH4EqT5 1645-1646 ! ! alias exec t telnet alias exec sis show interface status !
I understand that I can do a pattern matching method using sed -i '/pattern/d' to remove it but that is not what I want as the values change from file to file. Any help would be much appreciated.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
sed seems like the right tool:
sed -i '/radius-server/!b;n;n;d' filename
How it works:
/radius-server/!b # as long as it's NOT 'radius-server' do nothing (branch to end) n # read next line (replace current line with next line) n # same as above - we now read 2 lines d # delete the current line
UPDATE – to modify multiple files, simply use glob instead of filename, e.g.
sed -i '/radius-server/!b;n;n;d' *
Method 2
Unless you have GNU awk 4.1.0 or later…
You won’t have such an option as sed’s -i option so instead do:
for file in *
do
awk -v lines=2 'BEGIN { ignore = -1 } /radius-server/ { ignore = NR + lines } NR != ignore { print }' "$file"
done > result.txt
This works as follows:
BEGIN { ignore = -1 } # initialize ignore with -1 so NR will never
# be equal to it by accident
/radius-server/ { ignore = NR + lines } # when the radius-server is found, set ignore to the
# line we want to ignore
NR != ignore { print } # unless the current line is that line, print
# it.
Note: the -i is not magic, it is also creating a temporary file sed just handles it for you.
Update
If you need to recurse into subdirectories:
find . -type f -exec awk ... {} ; > result.txt
In both cases, you should probably put result.txt in a different directory. Otherwise, it will be matched and used as an input file.
Method 3
PATH_TO_FOLDER="/some/path/to/folder/"
FILE_EXTENSION=".ext"
FILES=$(ls ${PATH_TO_FOLDER}/*${FILE_EXTENSION})
for FILE in $FILES; do
FILENAME=$(basename $FILE ${FILE_EXTENSION})
TMP_FILE=${PATH_TO_FOLDER}/${FILENAME}.tmp
awk -v Lines=2 '{if($0~"radius-server"){
print;
for(i=0;i<=Lines;i++)
{
getline;
if(i==Lines){
next;
}else{
print;
}
}
}
else{
print;
}
}' $FILE > $TMP_FILE
mv ${TMP_FILE} ${FILE}
In principle this should work. Basically if the line contains radius-server that line will be printed and then it will iterate over the next 3 lines 0 will print the first line 1 will print the second line and then 3 will skip the third line altogether. For all other cases the lines are printed as is.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0