Sed Strings
Sed - Manipulating Strings
Section titled “Sed - Manipulating Strings”Substitute Command (s)
Section titled “Substitute Command (s)”The substitute command, s, is one of Sed’s most powerful features, used for finding and replacing text. Its basic syntax is:
[address1[,address2]]s/pattern/replacement/[flags]Where:
address1, address2: Optional line addresses or patterns to restrict the command’s scope.s: The substitute command./: A delimiter. While/is common, any character (except backslash or newline) can be used, e.g.,s|pattern|replacement|ors#pattern#replacement#. This is useful ifpatternorreplacementcontains slashes.pattern: A regular expression to search for.replacement: The string to replace the matched pattern with. Special characters like&(the entire matched pattern) and\1through\9(captured groups) can be used here.flags: Optional modifiers that change the substitution behavior.
Common Flags:
g: Global. Replace all occurrences ofpatternon the line, not just the first.N(a number): Replace only the Nth occurrence.p: Print. If a substitution occurs, print the (modified) line. Often used with-nto print only changed lines.w file: Write. If a substitution occurs, write the (modified) line tofile.iorI(GNU Sed extension): Case-insensitive matching forpattern.
Let’s use a sample books.txt file:
- A Storm of Swords, George R. R. Martin, 1216
- The Two Towers, J. R. R. Tolkien, 352
- The Alchemist, Paulo Coelho, 197
- The Fellowship of the Ring, J. R. R. Tolkien, 432
- The Pilgrimage, Paulo Coelho, 288
- A Game of Thrones, George R. R. Martin, 864
Example 1: Replace the first comma with a pipe.
[user]$ sed 's/,/ | /' books.txtOutput:
1) A Storm of Swords | George R. R. Martin, 12162) The Two Towers | J. R. R. Tolkien, 3523) The Alchemist | Paulo Coelho, 1974) The Fellowship of the Ring | J. R. R. Tolkien, 4325) The Pilgrimage | Paulo Coelho, 2886) A Game of Thrones | George R. R. Martin, 864Notice only the first comma on each line is replaced. To replace all commas, use the g flag:
[user]$ sed 's/,/ | /g' books.txtOutput:
1) A Storm of Swords | George R. R. Martin | 12162) The Two Towers | J. R. R. Tolkien | 3523) The Alchemist | Paulo Coelho | 1974) The Fellowship of the Ring | J. R. R. Tolkien | 4325) The Pilgrimage | Paulo Coelho | 2886) A Game of Thrones | George R. R. Martin | 864Example 2: Replace commas only on lines containing “The Pilgrimage”.
[user]$ sed '/The Pilgrimage/s/,/ | /g' books.txtOutput:
1) A Storm of Swords, George R. R. Martin, 12162) The Two Towers, J. R. R. Tolkien, 3523) The Alchemist, Paulo Coelho, 1974) The Fellowship of the Ring, J. R. R. Tolkien, 4325) The Pilgrimage | Paulo Coelho | 2886) A Game of Thrones, George R. R. Martin, 864Example 3: Replace only the second comma with a pipe.
[user]$ sed 's/,/ | /2' books.txtOutput:
1) A Storm of Swords, George R. R. Martin | 12162) The Two Towers, J. R. R. Tolkien | 3523) The Alchemist, Paulo Coelho | 1974) The Fellowship of the Ring, J. R. R. Tolkien | 4325) The Pilgrimage, Paulo Coelho | 2886) A Game of Thrones, George R. R. Martin | 864Example 4: Print only changed lines (using -n and p flag).
[user]$ sed -n 's/Paulo Coelho/PAULO COELHO/p' books.txtOutput:
3) The Alchemist, PAULO COELHO, 1975) The Pilgrimage, PAULO COELHO, 288Example 5: Write changed lines to a file (using w flag).
[user]$ sed 's/Paulo Coelho/PAULO COELHO/w changed_authors.txt' books.txt > /dev/null # suppress normal output[user]$ cat changed_authors.txtOutput from cat changed_authors.txt:
3) The Alchemist, PAULO COELHO, 1975) The Pilgrimage, PAULO COELHO, 288Note: The original command sed -n 's/.../w file' would print nothing to stdout. If you want both default output and writing to file for changed lines, use sed 's/.../&/w file'. The example above explicitly redirects main output.
Example 6: Case-insensitive substitution (GNU Sed i flag).
[user]$ sed -n 's/pAuLo CoElHo/PAULO COELHO/pi' books.txtOutput:
3) The Alchemist, PAULO COELHO, 1975) The Pilgrimage, PAULO COELHO, 288Example 7: Using different delimiters to replace paths.
If you need to replace /usr/local/bin with /opt/bin, using / as a delimiter requires extensive escaping:
[user]$ echo "Path is /usr/local/bin" | sed 's/\/usr\/local\/bin/\/opt\/bin/'Output:
Path is /opt/binUsing an alternative delimiter like |, #, or ! makes it much more readable:
[user]$ echo "Path is /usr/local/bin" | sed 's|/usr/local/bin|/opt/bin|'Output:
Path is /opt/binCreating Substrings with Capturing Groups
Section titled “Creating Substrings with Capturing Groups”Sed allows you to capture parts of the matched pattern and reuse them in the replacement string. This is done using capturing groups.
In Basic Regular Expressions (BRE, Sed’s default), groups are defined with \( and \). The captured text can be referenced using \1 for the first group, \2 for the second, and so on.
If using Extended Regular Expressions (sed -E or sed -r), groups are ( and ), and still referenced by \1, \2, etc.
Consider the input string: “Three One Two”. We want to rearrange it to “One Two Three”.
[user]$ echo "Three One Two" | sed 's|\(\w\+\) \(\w\+\) \(\w\+\)|\2 \3 \1|'Explanation:
\(\w\+\): This is a capturing group.\w\+: Matches one or more word characters (GNU Sed extension;[[:alnum:]_]+is more portable for the “word character” concept). Escaped\+for BRE.
- The pattern
\(\w\+\) \(\w\+\) \(\w\+\)captures three words separated by spaces.\1captures “Three”\2captures “One”\3captures “Two”
\2 \3 \1: The replacement string reorders these captured groups.
Output:
One Two ThreeUsing ERE, the command is cleaner:
[user]$ echo "Three One Two" | sed -E 's|(\w+) (\w+) (\w+)|\2 \3 \1|'Example with comma-separated values:
[user]$ echo "Smith,John,123 Main St" | sed -E 's|([^,]+),([^,]+),(.+)|\2 \1, \3|'Output (rearranges to Firstname Lastname, Address):
John Smith, 123 Main StHere, [^,]+ matches one or more characters that are not a comma.
String Case Modification in Replacement (GNU Sed Extensions)
Section titled “String Case Modification in Replacement (GNU Sed Extensions)”GNU Sed provides special sequences in the replacement string to change the case of matched text or captured groups.
\L: Converts the rest of the replacement (or up to\E) to lowercase.\l: Converts the next character to lowercase.\U: Converts the rest of the replacement (or up to\E) to uppercase.\u: Converts the next character to uppercase.\E: Stops the case conversion started by\Lor\U.
Example 1: Using \L
[user]$ sed -n 's/Paulo/PA\LULO COELHO/p' books.txtOutput (PA followed by ulo in lowercase):
3) The Alchemist, PAulo COELHO, 1975) The Pilgrimage, PAulo COELHO, 288Example 2: Using \u
[user]$ sed -n 's/Paulo/p\uaul\uo/p' books.txtOutput (p, then A, then ul, then O):
3) The Alchemist, pAulO Coelho, 1975) The Pilgrimage, pAulO Coelho, 288Example 3: Using \U
[user]$ sed -n 's/Paulo/\Upaulo/p' books.txtOutput (converts ‘paulo’ to ‘PAULO’):
3) The Alchemist, PAULO Coelho, 1975) The Pilgrimage, PAULO Coelho, 288Example 4: Using \U and \E
[user]$ sed -n 's/Paulo Coelho/Title: \U&\E - Author./p' books.txt # & refers to the whole match 'Paulo Coelho'Output (converts ‘Paulo Coelho’ to uppercase within the replacement):
3) The Alchemist, Title: PAULO COELHO - Author., 1975) The Pilgrimage, Title: PAULO COELHO - Author., 288Practical Application: Converting CSV to a formatted string.
Input data.csv:
name,age,city Alice,30,New York Bob,24,Los Angeles
[user]$ sed -E '1d; s/([^,]+),([^,]+),(.+)/Name: \U\1\E, Age: \2, City: \u\3/' data.csvExplanation:
1d: Deletes the header line.s/([^,]+),([^,]+),(.+)/.../: Captures three comma-separated fields.\1is name,\2is age,\3is city.
Name: \U\1\E: Prints “Name: ” followed by the name in uppercase.Age: \2: Prints “Age: ” followed by the age.City: \u\3: Prints “City: ” followed by the city with its first letter capitalized.
Output:
Name: ALICE, Age: 30, City: New YorkName: BOB, Age: 24, City: Los Angeles