Gnu sed: Difference between revisions
From wikinotes
(15 intermediate revisions by the same user not shown) | |||
Line 13: | Line 13: | ||
= Overview = | = Overview = | ||
<blockquote> | <blockquote> | ||
sed lets you manipulate text streams using | sed lets you manipulate text streams using [https://man.archlinux.org/man/core/sed/sed.1.en#COMMAND_SYNOPSIS commands] | ||
example commands: | example commands: | ||
Line 29: | Line 29: | ||
> my newline | > my newline | ||
> baz | > baz | ||
# multiple commands can be separated by a ';' | |||
# (lines not matching /bar/ will be deleted. AND lines matching bar will print their line number) | |||
echo 'foo\nbar\nbaz' | sed '/bar/!d;=' | |||
</syntaxhighlight> | </syntaxhighlight> | ||
By default, all commands operate on every line.<br> | By default, all commands operate on every line.<br> | ||
You can use | You can use [https://man.archlinux.org/man/core/sed/sed.1.en#Addresses addresses] to limit the scope of a command. | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
Line 45: | Line 49: | ||
# Limit scope of 'i' to an address-range | # Limit scope of 'i' to an address-range | ||
# ',' between two addresses selects all lines in between the matches (inclusively) | # ',' between two addresses selects all lines in between the matches (inclusively) | ||
# ( for range between /3/ and /5/, insert newline ) | |||
echo '1\n2\n3\n4\n5\n6' | sed '/3/,/5/i \newline' | echo '1\n2\n3\n4\n5\n6' | sed '/3/,/5/i \newline' | ||
> 1 | > 1 | ||
Line 60: | Line 65: | ||
= Usage = | = Usage = | ||
<blockquote> | <blockquote> | ||
< | == Cookbook == | ||
<blockquote> | |||
Replace 'aaa' with 'bbb' | |||
<syntaxhighlight lang="bash"> | |||
cat echo "aaa_stuff_aaa" \ | cat echo "aaa_stuff_aaa" \ | ||
| sed 's_aaa_bbb_g' | | sed 's_aaa_bbb_g' | ||
</syntaxhighlight> | |||
regex search/replace | |||
# | <syntaxhighlight lang="bash"> | ||
# replace one-or-more 'a's with a single 'b' | |||
cat echo "aaa_stuff_aaa" \ | cat echo "aaa_stuff_aaa" \ | ||
| sed -E 's_[a]*_b_g' | | sed -E 's_[a]*_b_g' | ||
Line 74: | Line 83: | ||
cat echo "aaa_stuff_aaa" \ | cat echo "aaa_stuff_aaa" \ | ||
| sed -E 's_\([a]*\)\(stuff\)_\2\n' | | sed -E 's_\([a]*\)\(stuff\)_\2\n' | ||
</syntaxhighlight> | |||
search/replace and write file | |||
<syntaxhighlight lang="bash"> | |||
# Replace file contents | # Replace file contents | ||
sed -i"bak" "s_aaa_bbb_g" /path/to/file | sed -i"bak" "s_aaa_bbb_g" /path/to/file | ||
</ | </syntaxhighlight> | ||
print range between two-matches, and prepend line-number | |||
<syntaxhighlight lang="bash"> | |||
# Print lines from address-range, prepending line-number | |||
echo '1\n2\n3\n4\n5\n6' \ | |||
| sed '/3/,/5/!d;=' `# delete non-matching lines, prepend line-no above each matching line` \ | |||
| sed 'N;s/\n/:\t/' `# include next-line in match, replace '\n' with ':\t' | |||
> 3: 3 | |||
> 4: 4 | |||
> 5: 5 | |||
</syntaxhighlight> | |||
Extract key-value from INI section | |||
<syntaxhighlight lang="bash"> | |||
delete_non_section_lines='/^\[MY_SECTION\]/,/^\[/!d' | |||
delete_non_matching_keys='/^[ ]*MY_KEY[ ]*=/!d;' | |||
get_value='s/.*=[ ]*//' | |||
value=$(cat ~/some-config.ini \ | |||
| sed -E "${delete_non_section_lines};${delete_non_matching_keys};${get_value}") | |||
</syntaxhighlight> | |||
</blockquote><!-- Cookbook --> | |||
== Addresses == | |||
<blockquote> | |||
<syntaxhighlight lang="bash"> | |||
/foo/ # select lines matching regex | |||
/foo/,/bar/ # select lines matching regex(foo), regex(bar), and all lines in between | |||
/foo/! # select lines NOT matching /foo/ (requires command after '!') | |||
5,10 # lines 5-10 inclusively | |||
</syntaxhighlight> | |||
</blockquote><!-- Addresses --> | |||
</blockquote><!-- Usage --> | </blockquote><!-- Usage --> |
Latest revision as of 01:55, 30 April 2022
Gnu sed performs search/replace within stdin or files.
See also bsd sed.
Documentation
man sed
https://man.archlinux.org/man/core/sed/sed.1.en
Overview
sed lets you manipulate text streams using commands
example commands:
# 's' command search/replaces text echo 'foo_bar_baz' | sed 's/bar/BAR/g' > foo_BAR_gaz # 'i'/'a' commands prepend/append newlines to each line echo 'foo\nbar\nbaz' | sed 'i \my newline' > my newline > foo > my newline > bar > my newline > baz # multiple commands can be separated by a ';' # (lines not matching /bar/ will be deleted. AND lines matching bar will print their line number) echo 'foo\nbar\nbaz' | sed '/bar/!d;='By default, all commands operate on every line.
You can use addresses to limit the scope of a command.# Limit scope of 'i' command to lines matching /bar/ echo 'foo\nbar\nbaz\bat' | sed '/bar/i \newline' > foo > newline > bar > baz > bat # Limit scope of 'i' to an address-range # ',' between two addresses selects all lines in between the matches (inclusively) # ( for range between /3/ and /5/, insert newline ) echo '1\n2\n3\n4\n5\n6' | sed '/3/,/5/i \newline' > 1 > 2 > newline > 3 > newline > 4 > newline > 5 > 6
Usage
Cookbook
Replace 'aaa' with 'bbb'
cat echo "aaa_stuff_aaa" \ | sed 's_aaa_bbb_g'regex search/replace
# replace one-or-more 'a's with a single 'b' cat echo "aaa_stuff_aaa" \ | sed -E 's_[a]*_b_g' # Group matching (\2 is a variable that refers to the # second match group. In this case, 'stuff' cat echo "aaa_stuff_aaa" \ | sed -E 's_\([a]*\)\(stuff\)_\2\n'search/replace and write file
# Replace file contents sed -i"bak" "s_aaa_bbb_g" /path/to/fileprint range between two-matches, and prepend line-number
# Print lines from address-range, prepending line-number echo '1\n2\n3\n4\n5\n6' \ | sed '/3/,/5/!d;=' `# delete non-matching lines, prepend line-no above each matching line` \ | sed 'N;s/\n/:\t/' `# include next-line in match, replace '\n' with ':\t' > 3: 3 > 4: 4 > 5: 5Extract key-value from INI section
delete_non_section_lines='/^\[MY_SECTION\]/,/^\[/!d' delete_non_matching_keys='/^[ ]*MY_KEY[ ]*=/!d;' get_value='s/.*=[ ]*//' value=$(cat ~/some-config.ini \ | sed -E "${delete_non_section_lines};${delete_non_matching_keys};${get_value}")Addresses
/foo/ # select lines matching regex /foo/,/bar/ # select lines matching regex(foo), regex(bar), and all lines in between /foo/! # select lines NOT matching /foo/ (requires command after '!') 5,10 # lines 5-10 inclusively