sed

最後更新: 2019-12-10

介紹

Sed (stream editor)

很詳細的 Documment: http://www.grymoire.com/Unix/Sed.html

目錄

  1. 常用 options
  2. Command
  3. 刪除
  4. 取代(substitution)
  5. "|" ":" "@"
  6. print (簡寫 p)
  7. Comments
  8. Print line number with =
  9. Transform with y (1對1的)
  10. Grouping with { and }
  11. Adding(a), Inserting(i), Changing lines
  12. Writing a file with the 'w' command
  13. Change configuration files setting value (ini file)

 


常用 options

 

# version

sed --version

GNU sed version 4.2.1

-n, --quiet ( 在 print(p) 時只會 output 中 pattern 的 line )

-e script

-f script-file

修改 File

當沒有 -i 或 -c 時, 只會在 stdout 輸出改過後的內容

# edit files in place (makes backup if extension supplied)

-i[SUFFIX], --in-place=[SUFFIX]

# use copy instead of rename when shuffling files in -i mode.

-c, --copy

# use extended regular expressions in the script.

-r, --regexp-extended

 


Silent mode(-n)

 

$ cat test.txt

first
second
third

# prints only lines 2 through 3, as requested

$ sed -n '2,3p' test.txt

second
third

# prints each line (automatically), AND ALSO prints lines 2-3 a second time

$ sed '2,3p' test.txt

first
second
second
third
third

By default, sed will print out the pattern space at the end of each cycle through the script.

These options(-n) disable this automatic printing,  and sed will only produce output when explicitly told to via the p command.

# 在 "s/" 情況

sed -n 's/t/T/' test.txt - replaces "t" with "T" on each line, but doesn't print the result due to -n

sed 's/t/T/' test.txt - replaces "t" with "T" on each line, and automatically prints the result

 


Command

 

  • s/regexp/replacement/         <--- 用得最多
  • p
  • d
  • w filename
  • y
  • =

 


Delimiter

 

/ _ : | @

 

一切為了簡化

將 path.txt 的內容由 /opt/name/bin 變成 /opt/tools/bin

sed 's/\/opt\/name\/bin/\/opt\/tools\/bin/g' path.txt

應用:

sed 's@/opt/name/bin@/opt/tools/bin@g' path.txt

 


實際使用

 

刪除:

 

# 刪除第一行

sed -e '1d' /etc/services

# 刪除第2至第4行

sed '2,4d' test

# Remove line "matched" by a regular expression

# 刪除有英文字"awk" 的所有行

sed '/awk/d' filename.txt

# Remove all empty lines:

sed '/^$/d' filename.txt    
sed '/./!d' filename.txt

# 刪除以 ".." 開始的

sed -i 's/^..//' > domain.txt

# by eliminating one containing digital characters (at least 1 digit) located at the end of the line)

sed '/[0-9/][0-9]*$/d' filename.txt

 


取代(substitution)

 

把在 testfile 檔內的每行 is 取代 成 are, 然後 output 到 stdout

sed 's/is/are/g' testfile

sed 's#is#are#g' testfile

Remark

 - The s stands for substitute,

 - the g stands for global. which means that all matching occurrences in the line would be replaced

    有些版本的 sed 是不用加 /g 的也是 global replacement

直接 replace file

sed -i 's/is/are/g' testfile

# interesting usage insert / remove "#"

# insert "#" at the beginning of a line

sed -i '3 s/^/#/' test.txt

# remove "#" at the beginning of a line

sed -i '3 s/^#//' test.txt

# add string to each line in file

sed -e 's/$/string after each line/' -i filename

 


Regular Expression

 

Position

^    Matches the beginning of the line
$    Matches the end of the line

/^#/            Will match any line that begins with a '#'
/^$/            Will match all blank lines
/}$/            Will match any lines that ends with '}' (no spaces)
/} *$/          Will match any line ending with '}' followed by zero or more spaces

數量

*    Will match zero or more occurrences of the previous character

字符

.    Matches any single character <--- 真正的"." 是 "\."

/./             Will match any line that contains at least one character
/../            Will match any line that contains at least two characters

[]   Matches all the characters inside the [ ]

/[abc]/         Will match any line that contains a lowercase 'a', 'b', or 'c'
/^[abc]/        Will match any line that begins with an 'a', 'b', or 'c'

Ampersand (&):

# 用 sed 扮 grep

cat file.txt

abcd
bcde
cdef

sed -n -e's/pattern/&/p' <file.txt

abcd
bcde

# Duplicate

echo "123 abc" | sed 's/[0-9]*/& &/'

123 123 abc

P.S.

"&"                 - corresponds to the pattern found

"(pattern)"    - \1  through  \9  to  refer to the corresponding matching

Example

# -n option which tells sed not to print

# p flag which tells sed to print what is matched

ls -og /sys/block/sd*

lrwxrwxrwx 1 0 May 17 19:24 /sys/block/sda ->
 ../devices/pci0000:00/0000:00:11.0/ata1/host0/target0:0:0/0:0:0:0/block/sda

ls -l /sys/block/sd* | sed -n 's/.*\(sd.\) -.*\(ata.*\)\/h.*/\2 => \1/p'

 


print (簡寫 p)

 

/p - print

 

sed -n -e '/regexp/p' /path/to/my/test/file | more

  • -n 只print 有修改的行

By default, sed prints every line. If it makes a substitution, the new text is printed instead of the old one.

 

找出檔案在 N 與 M之間的內容(N,M 可以是數字式 patten):

usage:

sed -n -e'N,Mp' file.txt

i.e.

sed -n -e'6,7p' test.txt

sed -n '/begin/,/end/p' test.txt

 


Comment

 

Sed comments are lines where the first non-white character is a "#."

On many systems, sed can have only one comment, and it must be the first line of the script.

 


Print line number with =

 

sed -n '/PATTERN/ =' file

 


Transform with y (1對1對換)

 

test.txt

aaaaaa11111
bbbbbb22222
cccccc33333
dddddd44444

sed 'y/bbbbbb/eeeeee/' test.txt

aaaaaa11111
eeeeee22222
cccccc33333
dddddd44444

b 與  e 必須一樣長度
 


Multiple commands for one address(Grouping with { and })

 

Sometimes, you may want to specify multiple commands that will apply to a single address.

This comes in especially handy when you are performing lots of 's///' to transform words or syntax in the source file.

To perform multiple commands per address, enter your sed commands in a file, and use the '{ }' characters to group commands, as follows:

i.e.

1,20{
    s/[Ll]inux/GNU\/Linux/g
    s/samba/Samba/g
    s/posix/POSIX/g
}

i.e.

1,/^END/{
    s/[Ll]inux/GNU\/Linux/g
    s/samba/Samba/g
    s/posix/POSIX/g
    p
}

This example will apply all the commands between '{ }' to the lines starting at 1 and up to a line beginning with the letters "END",

or the end of file if "END" is not found in the source file.

i.e.

#!/bin/sh
# This is a Bourne shell script that removes #-type comments
# between 'begin' and 'end' words.
sed -n '
    /begin/,/end/ {
         s/#.*//
         s/[ ^I]*$//
         /^$/ d
         p
    }
'

 


Adding(a|r), Inserting(i), Changing lines

 

Append a line with 'a'

The "a" command appends a line after the range or pattern. This example will add a line after every line with "WORD"

#!/bin/sh
sed '
/WORD/ a\
Add this line after every line with WORD
'

P.S.

lines are continued by ending the previous line with a "\".

Append a file

r filename             # Append text read from filename.

sed append to end of file

echo "Line" >> /etc/sudoers

Insert a line with 'i'

You can insert a new line before the pattern with the "i" command:

#!/bin/sh
sed '
/WORD/ i\
Add this line before every line with WORD
'

在 match 的行的行頭 insert "#"

Usage:

sed /match/s/^/#/ filename

i.e.

sed /authn_dbd_module/s/^/#/ 00-base.conf

Change a line with 'c'

You can change the current line with a new line.

#!/bin/sh
sed '
/WORD/ c\
Replace the current line with the line
'

i.e.

cat myfile

aaaaaa11111
bbbbbb22222
cccccc33333
dddddd44444

sed '/bbbbbb/c eeeee' myfile

cat myfile

aaaaaa11111
eeeee
cccccc33333
dddddd44444

A "d" command followed by a "a" command won't work, as I discussed earlier.

The "d" command would terminate the current actions. You can combine all three actions using curly braces:

#!/bin/sh
sed '
/WORD/ {
i\
Add this line before
a\
Add this line after
c\
Change the line to this one
}'

 


Writing a file with the 'w' command

 

sed -n 's/^[0-9]*[02468] /&/w even' < file

I used the "&" in the replacement part of the substitution command so that the line would not be changed.

A simpler example is to use the "w" command, which has the same syntax as the "w" flag in the substitute command

 


Change configuration files setting value (ini file)

 

cat test.ini

setting1=false
setting2=false

方法1

replaceValue=true

sed -i -r "s/setting1=.*/setting1=$replaceValue/" test.ini

OR

sed -i -e "/setting1=/ s/=.*/=$replaceValue/" test.ini

方法2

sed -i "/setting1=/d"  test.ini
echo "setting1=$replaceValue"  >> test.ini