Gnu sed: Difference between revisions

From wikinotes
 
(7 intermediate revisions by the same user not shown)
Line 67: Line 67:
== Cookbook ==
== Cookbook ==
<blockquote>
<blockquote>
Really common/simple examples
Replace 'aaa' with 'bbb'
<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
# Replace 'aaa' with 'bbb'
cat echo "aaa_stuff_aaa" \
cat echo "aaa_stuff_aaa" \
     | sed 's_aaa_bbb_g'
     | sed 's_aaa_bbb_g'
</syntaxhighlight>


 
regex search/replace
# Regex
<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 82: 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
# Print lines from address-range, prepending line-number
echo '1\n2\n3\n4\n5\n6' \
echo '1\n2\n3\n4\n5\n6' \
Line 93: Line 99:
> 3:    3
> 3:    3
> 4:    4
> 4:    4
> 5:    5  
> 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>
</syntaxhighlight>
</blockquote><!-- Cookbook -->
</blockquote><!-- Cookbook -->
Line 103: Line 119:
/foo/,/bar/  # select lines matching regex(foo), regex(bar), and all lines in between
/foo/,/bar/  # select lines matching regex(foo), regex(bar), and all lines in between
/foo/!      # select lines NOT matching /foo/ (requires command after '!')
/foo/!      # select lines NOT matching /foo/ (requires command after '!')
5,10        # lines 5-10 inclusively
</syntaxhighlight>
</syntaxhighlight>
</blockquote><!-- Addresses -->
</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/file

print 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:    5

Extract 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