Gnu sed: Difference between revisions

From wikinotes
Line 67: Line 67:
== Cookbook ==
== Cookbook ==
<blockquote>
<blockquote>
Really common/simple examples
Replace 'aaa' with 'bbb'
Replace 'aaa' with 'bbb'
<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">

Revision as of 18:04, 31 October 2021

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

# basics
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

compound commands

# 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
header_match='^\[MY_SECTION\]'
next_header_match='^\['
delete_non_section_lines="/${header_match}/,/${next_header_match}/!d"

key_match='^[ ]*'"$2"'[ ]*='
delete_non_matching_keys="/${key_match}/!d;"

isolate_value="s/.*=[ ]*//"
value=$(cat ~/some-config.ini | sed -E "${delete_non_section_lines};${delete_non_matching_keys};${isolate_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 '!')