rokkonet

PC・Androidソフトウェア・アプリの開発・使い方に関するメモ

sedコマンド 変数・文字列展開・特殊文字の解釈

2021 Feb. 28.
2021 Feb. 21.

sed基本構文

sed -e Script    # 拡張正規表現を使わない
sed -E Script    # 拡張正規表現を使う
# -Eは-rでも同じ

Script全体を引用符で括る要否

  • Scriptを全体を必ずしも引用符で括る必要はない。
  • Script文字列はまずシェルに渡されて展開され、その後、sedに渡される。
  • シェルでの展開は通常の文字列の扱いと同じ。
  • 引用符で括らなければ展開される。
  • ダブルクォーテーションで括れば一部($ ` \ ドル変数展開、バッククォートコマンド置換、バックスラッシュエスケープ)が展開される。
  • シングルクォーテーションで括れば展開されない。
  • シェルでの展開を踏まえて変数・引用符を記述する。


シェル変数のsedでの利用

  • Scriptを引用符で括らなければ、変数がシェルで展開された上でsedに渡される。変数に空白が含まれていたら空白で文字列が分割されてしまう。
  • Scriptを二重引用符で括ると、変数はシェルで展開された上でsedに渡されるが、変数に空白が含まれていても文字列全体が1つのリテラルと扱われる。
  • Script文字列内の変数・エスケープ文字・引用符の有無に応じて、Script文字列の引用符括りの要否を判断する。

特殊文字の解釈

\t
$ Str=$'\t'$'\t'"attb"$'\t'$'\t'"cttd"
$ echo "$Str"
                attb            cttd

$ echo "$Str" | sed -E s/\t//g
                ab              cd

引用符に括られない+はメタ文字と解される。
echo "$Str" | sed -E s/\t+//
                ab              cttd

$ Char=\t
$ echo $Char
t
$ echo "$Char"
t
$ echo -e "$Char"
t
$ Str=$'\t'$'\t'"attb"$'\t'$'\t'"cttd"
$ echo "$Str" | sed -E 's/\t//g'
attbcttd

シングルクォーテーションで括られた+はメタ文字と解される。
$ echo "$Str" | sed -E 's/\t+//'
attb            cttd
$ Str=$'\t'$'\t'"attb"$'\t'$'\t'"cttd"
$ echo "$Str" | sed -e s/\t//g
                ab              cd

拡張正規表現でない場合、+はメタ文字ではなく、次の例では\tで表されたtと+、つまり t+ というリテラルがマッチ対象。
$ echo "$Str" | sed -e s/\t+//
                attb            cttd

\t+がt+であることの確認
$ Str2=t+t+sbt+t+cd
$ echo $Str2
t+t+sbt+t+cd

$ echo "$Str2"
t+t+sbt+t+cd

$ echo "$Str2" | sed -e s/\t+//g
sbcd

$ echo "$Str2" | sed -e s/\t+//
t+sbt+t+cd

\+は1つの+と解される。次の例では t+ というリテラルがマッチ対象。
$ Str=$'\t'$'\t'"attb"$'\t'$'\t'"cttd"
$ echo "$Str" | sed -e s/\t\+//
                attb            cttd

\+が1つの+とシェルに認識される確認。
$ Str3=t\+t\+sbt\+t\+cd
$ echo "$Str3"
t+t+sbt+t+cd

$ echo $Str3
t+t+sbt+t+cd

$ echo -e $Str3
t+t+sbt+t+cd

$ echo -e "$Str3"
t+t+sbt+t+cd
$ Str=$'\t'$'\t'"attb"$'\t'$'\t'"cttd"
$ echo "$Str" | sed -e "s/\t//g"
attbcttd

+はメタ文字ではなく、タブと+が連続するリテラルがマッチ対象。
$ echo "$Str" | sed -e "s/\t+//"
                attb            cttd

+がメタ文字ではなく、\+がメタ文字であることの確認
$ Str4=++ab++cd
$ echo $Str4 | sed -e 's/+//g'
abcd

$ echo $Str4 | sed -e 's/+\+//'
ab++cd



Line=$'\t'"abc    bd "$'\t'"ef  "$'\t'

$ echo "$Line"
	abc    bd 	ef  	

$ echo "$Line" | sed -E 's/\t+/ /'
 abc    bd 	ef  	

$ echo "$Line" | sed -E 's/\t+/ /g'
 abc    bd  ef   

$ echo "$Line" | sed -E s/\t+/ /g
sed: -e expression #1, char 5: `s' コマンドが終了していません

$ echo "$Line" | sed -E s/\t+//g
	abc    bd 	ef  	

$ echo "$Line" | sed -E 's/\t+//g'
abc    bd ef  

$ echo "$Line" | sed -e 's/\t+//g'
	abc    bd 	ef
$ Line=$'\t'$'\t'"abc    bd  "$'\t'$'\t'"  ef"$'\t'$'\t'"  gh"

$ echo "$Line"
		abc    bd  		  ef		  gh

$ echo "$Line" | sed -E 's/\t+/ /'
 abc    bd  		  ef		  gh

$ echo "$Line" | sed -E "s/\t+/ /"
 abc    bd  		  ef		  gh

$ echo "$Line" | sed -E 's/\t\+/ /'
		abc    bd  		  ef		  gh

$ echo "$Line" | sed -E "s/\t\+/ /"
		abc    bd  		  ef		  gh

$ echo "$Line" | sed -E 's/\t+/ /g'
 abc    bd     ef   gh

$ echo "$Line" | sed -E "s/\t\+/ /g"
		abc    bd  		  ef		  gh

$ echo "$Line" | sed -E s/\t+//g
		abc    bd  		  ef		  gh

$ echo "$Line" | sed -E 's/\t+//g'
abc    bd    ef  gh

$ echo "$Line" | sed -E "s/\t+//g"
abc    bd    ef  gh

$ echo "$Line" | sed -E s/\t\+//g
		abc    bd  		  ef		  gh

$ echo "$Line" | sed -E 's/\t\+//g'
		abc    bd  		  ef		  gh

$ echo "$Line" | sed -E "s/\t\+//g"
		abc    bd  		  ef		  gh
$ Line=$'\t'$'\t'"abc    bd  "$'\t'$'\t'"  ef"$'\t'$'\t'"  gh"

$ echo "$Line"
		abc    bd  		  ef		  gh

$ echo "$Line" | sed -e 's/\t+/ /'
		abc    bd  		  ef		  gh

$ echo "$Line" | sed -e "s/\t+/ /"
		abc    bd  		  ef		  gh

$ echo "$Line" | sed -e 's/\t\+/ /'
 abc    bd  		  ef		  gh

$ echo "$Line" | sed -e "s/\t\+/ /"
 abc    bd  		  ef		  gh

$ echo "$Line" | sed -e 's/\t+/ /g'
		abc    bd  		  ef		  gh

$ echo "$Line" | sed -e "s/\t\+/ /g"
 abc    bd     ef   gh

$ echo "$Line" | sed -e s/\t+//g
		abc    bd  		  ef		  gh

$ echo "$Line" | sed -e 's/\t+//g'
		abc    bd  		  ef		  gh

$ echo "$Line" | sed -e "s/\t+//g"
		abc    bd  		  ef		  gh

$ echo "$Line" | sed -e s/\t\+//g
		abc    bd  		  ef		  gh

$ echo "$Line" | sed -e 's/\t\+//g'
abc    bd    ef  gh

$ echo "$Line" | sed -e "s/\t\+//g"
abc    bd    ef  gh