1

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.

  • Please be aware that "in place" isn't. The tool writes to a temporary file and replaces the original on successful completion. – roaima Apr 30 '16 at 19:32
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' *
  • @don_crissti true, but then the awk solution doesn't work either, nor does the OP's awk matcher. arzyfex's solution fails because all pattern lines remain, whereas the OP clearly asked for n+2 to be deleted. – Dani_l Apr 30 '16 at 19:41
  • Exactly what I wanted. Thanks a lot for the help. :) – Zzrot Apr 30 '16 at 19:57
  • @don_crissti Add a good solution, and I'll delete mine. – Dani_l Apr 30 '16 at 20:01
  • @don_crissti I think part of the issue is undefined behavior for consecutive patterns - suppose you have 3 consecutive lines, according to the rule you have to delete line #3, but what about lines #4,#5 ? one interpretation would be to delete all 3 lines (last pattern +2 lines), but if last pattern is no more, does it still count for purpose of deleting #5? Are you supposed to delete a target if in same pass you deleted source for choosing the target? – Dani_l Apr 30 '16 at 20:08
  • @Dani_l How can you say that "arzyfex's solution fails because all pattern lines remain", As OP has already said, it worked for him/her. – Rahul May 1 '16 at 5:22
0

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.

  • Thanks, this does solve most of my problem. The only thing that has not been addressed is modifying it in place. Is there any way of editing the file and saving it? I don't want to create a temp file. I just want the original file(s) to be modified. Also, there are multiple files in the folder so that should be kept in mind. Much appreciated! – Zzrot Apr 30 '16 at 18:09
  • 1
    @Zzrot - are you on a gnu setup ? If not, your tools might not support editing in place. – don_crissti Apr 30 '16 at 18:30
  • @Zzrot : As don_crissti said, you won't be able to edit in place. but there is workaround for that. please refer my updated answer. – Rahul Apr 30 '16 at 19:04
  • @arzyfex Thanks but it still doesnt fully work for me. Essentially what i'm trying is to replace filename with * . where * reads all the files in the folder. So I don't think the edited version works still. Thanks for getting back so promptly. – Zzrot Apr 30 '16 at 19:18
  • @Zzrot - please add your awk flavor & version to your post. – don_crissti Apr 30 '16 at 19:24
0
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.