Sed
Internal
GNU sed vs. BSD sed
GNU sed supports extra functionality relative to the BDS sed - for example \L and \U functions to turn a character to lower and upper cases. macOS comes with the BSD sed, so that is why it's probably a good idea to make upgrading to GNU sed part of the configuring a new Mac.
This is how you know you're using a GNU sed:
This is how you know you're using a BSD sed:
Install
Command Line Options
-i
sed -i extension ... filename
Edit the file in-place, saving backups with the specified extension. If a zero-length extension is given, no backup will be saved:
sed -i '' ... filename
Commands
p
Print the current pattern space. Note that the pattern space is printed automatically, unless -n is used.
sed Regular Expressions
Insert a Line/Append in a Specific Position (line number) in a file
Figure out the line number:
# determine the last line that contains ^JAVA_OPTS local n n=$(cat ${f} | grep -n "^JAVA_OPTS=" | tail -1) || { echo "failed to determine the line number" 1>&2; exit 1; } n=${n%%:*}
Insert a line at line 'n':
# insert at line "n": cat ${f} | sed -e ${n}'a\ This line will be inserted at line number '"${n}"', and this '"${variable}"' will be substituted' > ${dest}
To append at a specific line number, determine the line number as before and effectively "substitute" (s) the line end with your addition:
cat ${f} | sed -e ${n}'s/$/this text will be appended at line number, and this '"${variable}"' will be substituted\n' > ${dest}
Insert Multiple Lines at a Specific Position in a File
Use the above recipe, and in the last phase, use:
cat ${f} | sed -e ${n}'a\ blah\ blah\ blah with variable substitution, etc' > ${dest}
Deleting with sed
Delete a Line that Matches a Certain Pattern
sed will delete a line identified by line number or if the line matches a regular expression pattern:
sed '{<n>|/<regex>/}d' <file-name>
where:
- n is the 1-based line number.
- /<regex>/ is the pattern.
Examples:
Delete the third line of the file
sed '3d' a.txt > b.txt
Delete all lines that match a certain pattern
sed '/b..h/d' a.txt > b.txt
Delete the last line
sed '$d' a.txt > b.txt
Delete Lines Between Certain "Addresses"
sed '<n1>,<n2>d' <file-name> sed '/<regex1/,/regex2/d' <file-name> sed '<n1>,/regex1/d' <file-name> sed '/regex1/,<n2>d' <file-name>
The addresses can be line numbers or regular expressions. Line numbers are 1-based.
- Line numbers and regular expressions can be combined, they're both treated as addresses.
Examples:
Delete all lines between line 2 and line 5 (inclusively)
sed '2,5d' a.txt > b.txt
Delete all lines between the occurrences of two regular expressions
sed '/red/,/blue/d' a.txt > b.txt
Delete Negation
sed can be used to delete all lines that do not match a certain pattern.
sed '/<regex>/!d' <file-name>
Printing with sed
Print a Line Specified by Its Number
Line numbering is 1-based. The following command suppresses the automatic display of the pattern space by specifying -n, then it loads the specified line in the pattern space and prints it:
sed -n <line_number>p <file>
The folding example prints line 12:
sed -n 12p a.txt
Replacing First Occurrence In a File
On Mac, use 1. I read that on other sed version I have to use 0:
sed -e '1,/pattern/s/pattern/replacement/' ${file} > ./tmp