M HYPE SPLASH
// updates

Delete lines that come after a line with a specific pattern in Shell

By Emily Wilson

I'm trying to delete all lines comes after a specific pattern in files.

I have many files, which all have the same structure:

Example:

file1

line 1
...
line x "here there is a specific pattern"
...
EOF

file n

line 1
...
line x "here there is a specific pattern"
...
EOF

I tried to get a simple solution, but since I have many files, I proceed with a long way :p

The pattern appears one time in each file.

So, I got all lines number which contains this pattern, and save in one file.

this is my code:

count=$(ls -f path_to_folder/*.txt | wc -l)
echo "Number of txt file : $count"
### for ((i=1;i < $count+1 ;i++)) { vt=$(grep -n PATTERN $i.txt | cut -d : -f 1) echo $vt >> PATTERN_line.txt }

Every line in PATTERN_line.txt contains the line number, in each file, where the pattern exists.

Now, I'm trying to use those numbers to delete all lines that come after the pattern to the file end.

This means I need to keep the file from the head to the patten line which must be included.

I appreciate your help

5

5 Answers

This is very trivial with text processing utilities. For example, using sed:

sed '1,/pattern/!d' file

Meaning, match every line from the first one to the one with pattern and delete all the non-matched lines. So, replace pattern with your pattern. If it contains /, you need to escape those characters. For example, if the pattern is pattern-with/character:

sed '1,/pattern-with\/character/!d' file

To actually edit files (rather than print the edited stream to stdout), you can use the -i flag:

sed -i '1,/pattern/!d' file

You can make a backup of the original file by adding an extension for the old file to -i. Take care here - you must not include a space before the extension.

sed -i.backup '1,/pattern/!d' file

sed takes multiple filename arguments. For example, to act on all the non-hidden files in the current directory you could use:

sed -i '1,/pattern/!d' *
5

Another solution, using awk:

awk '/specific-pattern/{stop=1} stop==0{print}' < input_file >> output_file

While the variable stop is 0 (which is is, by default), awk will print the current line. However, if the current line matches the regular expression /specific-pattern/, then stop will be set to 1. This makes stop==0 untrue, so awk will no longer execute the print statement.

Input is read from input_file and appended to output_file.

If you want to keep the line with the pattern, reverse the two parts of the awk script.

Thank you @Zanna

I found this solution :

for ((i=1;i < $count+1 ;i++))
sed -n '/PATTERN/q;p' $i.txt > file_out$i.txt

Thank you

1

Try this shell script. It take 2 argument as input. First argument is the input filename. And the second argument is the required pattern to search. It will delete lines after the pattern is matched for first time.

#!/bin/bash
touch temp.txt
while read line
do echo "$line" | grep "$2" &> /dev/null if [ $? -eq 0 ] then echo "$line" >> temp.txt mv temp.txt $1 echo "STATUS: Pattern matched. Successful operation..." exit 0 fi echo "$line" >> temp.txt
done < $1
echo "STATUS: Pattern not found. No lines are deleted..."
rm -f temp.txt
1
sed -i -e '/pattern/{n;N;d;}' ./infile

Delete two lines after the pattern, exclusive

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

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