How would I use sed to delete all lines in a text file that contain a specific string?
22 Answers
To remove the line and print the output to standard out:
sed '/pattern to match/d' ./infile
To directly modify the file – does not work with BSD sed:
sed -i '/pattern to match/d' ./infile
Same, but for BSD sed (Mac OS X and FreeBSD) – does not work with GNU sed:
sed -i '' '/pattern to match/d' ./infile
To directly modify the file (and create a backup) – works with BSD and GNU sed:
sed -i.bak '/pattern to match/d' ./infile
7 Comments
sed -i.bak "/str/d" ./infile deletes my entire file.sed -i.bak "\#$pattern_variable_containing_slashes#d" ./infileThere are many other ways to delete lines with specific string besides sed:
AWK
awk '!/pattern/' file > temp && mv temp file
Ruby (1.9+)
ruby -i.bak -ne 'print if not /test/' file
Perl
perl -ni.bak -e "print unless /pattern/" file
Shell (bash 3.2 and later)
while read -r line
do
[[ ! $line =~ pattern ]] && echo "$line"
done <file > o
mv o file
GNU grep
grep -v "pattern" file > temp && mv temp file
And of course sed (printing the inverse is faster than actual deletion):
sed -n '/pattern/!p' file
9 Comments
sed example have a different behaviour, it only greps! it should be something like sed -n -i '/pattern/!p' file.grep -v "pattern" file > temp; mv temp file This might apply to some of the other examples depending on the return value.seq -f %f 10000000 >foo.txt. sed d: time sed -i '' '/6543210/d' foo.txt real 0m9.294s. sed !p: time sed -i '' -n '/6543210/!p' foo.txt real 0m13.671s. (For smaller files, the difference is larger.)You can use sed to replace lines in place in a file. However, it seems to be much slower than using grep for the inverse into a second file and then moving the second file over the original.
e.g.
sed -i '/pattern/d' filename
or
grep -v "pattern" filename > filename2; mv filename2 filename
The first command takes 3 times longer on my machine anyway.
10 Comments
sed '/pattern/d' filename > filename2; mv filename2 filenameThe easy way to do it, with GNU sed:
sed --in-place '/some string here/d' yourfile
6 Comments
-r option (or -E, depending on your version). This enables the use of regex metacharacters +, ?, {...} and (...).You may consider using ex (which is a standard Unix command-based editor):
ex +g/match/d -cwq file
where:
+executes given Ex command (man ex), same as-cwhich executeswq(write and quit)g/match/d- Ex command to delete lines with givenmatch, see: Power of g
The above example is a POSIX-compliant method for in-place editing a file as per this post at Unix.SE and POSIX specifications for ex.
The difference with sed is that:
sedis a Stream EDitor, not a file editor.BashFAQ
Unless you enjoy unportable code, I/O overhead and some other bad side effects. So basically some parameters (such as in-place/-i) are non-standard FreeBSD extensions and may not be available on other operating systems.
4 Comments
man ex it gives me the man for vim, it seems ex is part of vim... if I understood right that means the pattern syntax for match is vimregex.com which is similar but different to POSIX and PCRE flavours?ex is using a temp file, just like every other sane tool, besides idk using ddsed, working on stream: the file (even big) don't have to be completely loaded into memory.I was struggling with this on Mac. Plus, I needed to do it using variable replacement.
So I used:
sed -i '' "/$pattern/d" $file
where $file is the file where deletion is needed and $pattern is the pattern to be matched for deletion.
I picked the '' from this comment.
The thing to note here is use of double quotes in "/$pattern/d". Variable won't work when we use single quotes.
3 Comments
sed requires a parameter after -i, so if you don't want a backup, you still have to add an empty string: -i ''sed -i "/$pattern/d" $file . Thank you for your answer.To get a inplace like result with grep you can do this:
echo "$(grep -v "pattern" filename)" >filename
1 Comment
bash shell or similar (not tcsh).I have made a small benchmark with a file which contains approximately 345 000 lines. The way with grep seems to be around 15 times faster than the sed method in this case.
I have tried both with and without the setting LC_ALL=C, it does not seem change the timings significantly. The search string (CDGA_00004.pdbqt.gz.tar) is somewhere in the middle of the file.
Here are the commands and the timings:
time sed -i "/CDGA_00004.pdbqt.gz.tar/d" /tmp/input.txt
real 0m0.711s
user 0m0.179s
sys 0m0.530s
time perl -ni -e 'print unless /CDGA_00004.pdbqt.gz.tar/' /tmp/input.txt
real 0m0.105s
user 0m0.088s
sys 0m0.016s
time (grep -v CDGA_00004.pdbqt.gz.tar /tmp/input.txt > /tmp/input.tmp; mv /tmp/input.tmp /tmp/input.txt )
real 0m0.046s
user 0m0.014s
sys 0m0.019s
2 Comments
SED:
AWK:
GREP:
Comments
perl -i -nle'/regexp/||print' file1 file2 file3
perl -i.bk -nle'/regexp/||print' file1 file2 file3
The first command edits the file(s) inplace (-i).
The second command does the same thing but keeps a copy or backup of the original file(s) by adding .bk to the file names (.bk can be changed to anything).
Comments
to show the treated text in console
cat filename | sed '/text to remove/d'
to save treated text into a file
cat filename | sed '/text to remove/d' > newfile
to append treated text info an existing file
cat filename | sed '/text to remove/d' >> newfile
to treat already treated text, in this case remove more lines of what has been removed
cat filename | sed '/text to remove/d' | sed '/remove this too/d' | more
the | more will show text in chunks of one page at a time.
2 Comments
sed -i '/text to remove/d' filename is the same as cat filename | sed '/text to remove/d'cat! 2. sed could do more than 1 command! sed -e '/text to remove/d;/remove this too/d' filename | more 3. you could enclose many pattern in one sed command: sed '/text to remove\|remove this too/d' filename | moreI found most of the answers not useful for me, If you use vim I found this very easy and straightforward:
:g/<pattern>/d
1 Comment
vim as opposed to sed you can use ex stackoverflow.com/a/33186317 beware that it's slower. What's nice about vim is you can \v<pattern> to avoid backslashitisCuriously enough, the accepted answer does not actually answer the question directly. The question asks about using sed to replace a string, but the answer seems to presuppose knowledge of how to convert an arbitrary string into a regex.
Many programming language libraries have a function to perform such a transformation, e.g.
python: re.escape(STRING)
ruby: Regexp.escape(STRING)
java: Pattern.quote(STRING)
But how to do it on the command line?
Since this is a sed-oriented question, one approach would be to use sed itself:
sed 's/\([\[/({.*+^$?]\)/\\\1/g'
So given an arbitrary string $STRING we could write something like:
re=$(sed 's/\([\[({.*+^$?]\)/\\\1/g' <<< "$STRING")
sed "/$re/d" FILE
or as a one-liner:
sed "/$(sed 's/\([\[/({.*+^$?]\)/\\\1/g' <<< "$STRING")/d"
with variations as described elsewhere on this page.
1 Comment
cat filename | grep -v "pattern" > filename.1
mv filename.1 filename
2 Comments
Just in case someone wants to do it for exact matches of strings, you can use the -w flag in grep - w for whole. That is, for example if you want to delete the lines that have number 11, but keep the lines with number 111:
-bash-4.1$ head file
1
11
111
-bash-4.1$ grep -v "11" file
1
-bash-4.1$ grep -w -v "11" file
1
111
It also works with the -f flag if you want to exclude several exact patterns at once. If "blacklist" is a file with several patterns on each line that you want to delete from "file":
grep -w -v -f blacklist file
1 Comment
-w, --word-regexp Select only those lines containing matches that form whole words. vs. -x, --line-regexp Select only those matches that exactly match the whole line. For a regular expression pattern, this is like parenthesizing the pattern and then surrounding it with ^ and $.You can use good old ed to edit a file in a similar fashion to the answer that uses ex. The big difference in this case is that ed takes its commands via standard input, not as command line arguments like ex can. When using it in a script, the usual way to accomodate this is to use printf to pipe commands to it:
printf "%s\n" "g/pattern/d" w | ed -s filename
or with a heredoc:
ed -s filename <<EOF
g/pattern/d
w
EOF