質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
sed

sedとは、POSIX環境のために作られたコマンドラインエディタです。sedは編集スクリプトの指示のもとに複数のファイルを編集し、標準出力にその結果を出力します。

Q&A

解決済

3回答

1975閲覧

sedコマンドでの正規表現の区切り文字について

rasum

総合スコア21

sed

sedとは、POSIX環境のために作られたコマンドラインエディタです。sedは編集スクリプトの指示のもとに複数のファイルを編集し、標準出力にその結果を出力します。

0グッド

0クリップ

投稿2022/01/16 06:35

編集2022/01/16 11:06

パス文字列が入ったシェル変数を扱って混乱したのですが、sedコマンドでの正規表現の区切り文字の考え方がよくわかりません。
下記の例からすると、区切り文字は「スラッシュ」「パイプ・パーセント等」「コロン等」で動作が異なり、「パイプ・パーセント等」を使うのが安全であり、削除の場合は最初の区切り文字の直前にバックスラッシュを置くのがよく、置換の場合は最初の区切り文字の直前にバックスラッシュを置いてはいけないようです。
区切り文字の種類、区切り文字直前のバックスラッシュの意味を日本語で理解できるサイト・資料はないでしょうか?

正規表現文字列にスラッシュが含まれる場合のsedの動作例

スラッシュを区切り文字とする場合

スラッシュ直前にバックスラッシュを付ければよい。
パスが格納されているシェル変数を正規表現にする時は扱いにくい。

cat FILE.txt | sed "/Reg\/Exp/d" => OK cat FILE.txt | sed "s/Reg\/Exp//" => OK

 
スラッシュを区切り文字とし、最初の区切り文字の直前にバックスラッシュを付けると削除と置換で動作が異なる。

cat FILE.txt | sed "\/Reg\/Exp/d" => OK cat FILE.txt | sed "s\/Reg\/Exp//" => NG。`s' コマンドが終了していません

 

パイプを区切り文字とする場合

削除と置換で動作が異なる。

cat FILE.txt | sed "|Reg/Exp|d" => NG。不明なコマンド: `|' cat FILE.txt | sed "s|Reg/Exp||" => OK

 
パイプを区切り文字とし、最初の区切り文字の直前にバックスラッシュを付けると、削除と置換で動作が異なる。

cat FILE.txt | sed "\|Reg/Exp|d" => OK cat FILE.txt | sed "s\|Reg/Exp|d||" => NG。`s' コマンドが終了していません

 

パーセントを区切り文字とする場合

削除と置換で動作が異なる。

cat FILE.txt | sed "%Reg/Exp%d" => NG。 不明なコマンド: `%' cat FILE.txt | sed "s%Reg/Exp%%" => OK

 
パーセントを区切り文字とし、最初の区切り文字の直前にバックスラッシュを付けると、削除と置換で動作が異なる。

cat FILE.txt | sed "\%Reg/Exp%d" => OK cat FILE.txt | sed "s\%Reg/Exp%%" => NG。`s' コマンドが終了していません
コロンを区切り文字とする場合
cat FILE.txt | sed ":Reg/Exp:d" => NG。FILE.txtのままが出力される cat FILE.txt | sed "s:Reg/Exp::" => OK

 
コロンを区切り文字とし、最初の区切り文字の直前にバックスラッシュを付けると、

cat FILE.txt | sed "\:Reg/Exp:d" => OK cat FILE.txt | sed "s\:Reg/Exp::" => NG。`s' コマンドが終了していません

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

sed: The Open Group Base Specifications Issue 7, 2018 edition IEEE Std 1003.1-2017 (Revision of IEEE Std 1003.1-2008)

Regular Expressions in sed

The sed utility shall support the BREs described in XBD Basic Regular Expressions, with the following additions:

In a context address, the construction "\cBREc", where c is any character other than <backslash> or <newline>, shall be identical to "/BRE/". If the character designated by c appears following a <backslash>, then it shall be considered to be that literal character, which shall not terminate the BRE. For example, in the context address "\xabc\xdefx", the second x stands for itself, so that the BRE is "abcxdef".

Editing Commands in sed

[2addr]s/BRE/replacement/flags
Substitute the replacement string for instances of the BRE in the pattern space. Any character other than <backslash> or <newline> can be used instead of a <slash> to delimit the BRE and the replacement. Within the BRE and the replacement, the BRE delimiter itself can be used as a literal character if it is preceded by a <backslash>.

投稿2022/01/16 07:43

melian

総合スコア19714

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

rasum

2022/01/16 10:40

melian様、ありがとうございます。 資料ページの紹介とアドレス指定についての引用をありがとうございます。 諸氏の解説を頂いて、やっと英文の言っていることがわかってきました。
guest

0

ベストアンサー

まず、置換の区切り文字は何でもいいです。どの区切り文字を使っても機能は同じです。
英字aを区切りにした、sed 'sapqraxyza'は、pqrxyzに置換します。ただ、見にくいので普通は記号ですね。

何でも良いので、普通は正規表現や置換後文字列の中に出てこない文字を使います。/はパスの区切りで出てくることもあるので、そういう時は別の文字(|とか#とか何でも)を使います。
何らかの理由で、正規表現や置換後文字列の中に区切り文字を使う時は、その前に\を置きます。
ルールとしてはそれだけです。

plain

1cat FILE.txt | sed "s/Reg\/Exp//" => OK 2→ 区切り文字が / で、Reg/Exp を 空文字列に置換。正規表現中に区切り文字が出てくるので \ を前置 3 4cat FILE.txt | sed "s\/Reg\/Exp//" => NG。`s' コマンドが終了していません 5→ 区切り文字が \ だが3つめの \ が無いのでエラー。区切り文字は3つ必要 6 7cat FILE.txt | sed "s|Reg/Exp|d||" => OK 8→ 区切り文字が | で、3つめの区切り文字の後に i や g 等のオプションじゃなくて 9 | という不明な文字があるのでエラーのはず。コピペミス? 10 11cat FILE.txt | sed "s\|Reg/Exp|d||" => NG。`s' コマンドが終了していません 12→ 区切り文字が \ だが \ が1つしか無いのでエラー。区切り文字は3つ必要 13 14cat FILE.txt | sed "s%Reg/Exp%%" => OK 15→ 区切り文字が % で、Reg/Exp を 空文字列に置換 16 17cat FILE.txt | sed "s\%Reg/Exp%%" => NG。`s' コマンドが終了していません 18→ 区切り文字が \ だが \ が1つしか無いのでエラー。区切り文字は3つ必要 19 20cat FILE.txt | sed "s:Reg/Exp::" => OK 21→ 区切り文字が : で、Reg/Exp を 空文字列に置換 22 23cat FILE.txt | sed "s\:Reg/Exp::" => NG。`s' コマンドが終了していません 24→ 区切り文字が \ だが \ が1つしか無いのでエラー。区切り文字は3つ必要

sed /reg/dのようにコマンドの前に付けてコマンドの対象行を指定する場合は若干違います。
通常は区切り文字として/を使いますが、正規表現中に/がたくさん出てくるなどで別の文字を使いたい場合は、先頭に\を書きます。正規表現末の区切り文字には\を付けません。
sed '\#reg#d'
ルールとしてはそれだけです。
また、(コマンド先頭の位置の):は、sed構文上「ラベル定義」という別の意味を持っています(後述)。

Plain

1cat FILE.txt | sed "/Reg\/Exp/d" => OK 2→ Reg/Exp を含む行を削除 3 4cat FILE.txt | sed "\/Reg\/Exp/d" => OK 5→ Reg/Exp を含む行を削除。\ は不要だが付けてもいい 6 7cat FILE.txt | sed "|Reg/Exp|d" => NG。不明なコマンド: `|' 8→ sedの構文として存在しない書き方 9 10cat FILE.txt | sed "\|Reg/Exp|d" => OK 11→ 区切り文字が | で、Reg/Exp を含む行を削除 12 13cat FILE.txt | sed "%Reg/Exp%d" => NG。 不明なコマンド: `%' 14→ sedの構文として存在しない書き方 15 16cat FILE.txt | sed "\%Reg/Exp%d" => OK 17→ 区切り文字が % で、Reg/Exp を含む行を削除 18 19cat FILE.txt | sed ":Reg/Exp:d" => NG。FILE.txtのままが出力される 20→ sedでは分岐(C等のgoto文相当)が使えるので、その分岐先を指定するラベル文があります。 21これは、Reg/Exp:d というラベルを定義しています。 22動作をするコマンドは何もないので、データはそのまま出力されます 23 24cat FILE.txt | sed "\:Reg/Exp:d" => OK 25→ 区切り文字が : で、Reg/Exp を含む行を削除

以上のルールは全部man sedに書いてあります。日本語manがインストールされてない場合は、https://linuxjm.osdn.jp/html/GNU_sed/man1/sed.1.html を参照。

投稿2022/01/16 07:24

編集2022/01/16 12:53
otn

総合スコア84505

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

rasum

2022/01/16 10:16

otn様、詳細にありがとうございます。 「cat FILE.txt | sed "s|Reg/Exp|d||" => OK」はコピペミスです。 「cat FILE.txt | sed "s|Reg/Exp||" => OK」でした。 「コロンはラベルを示す特殊文字」、わかりました。 「区切り文字は何でもよい」というのはmanのアドレス指定に関する \cregexpc でしょうね。 sコマンド直後のバックスラッシュについては、バックスラッシュ単独が区切り文字となるということなので、 cat FILE.txt | sed "s\Reg/Exp\\\\" とすると、正しく動作しました。 「dコマンドで区切り文字をスラッシュにしない時は、先頭にバックスラッシュを付ける」というルールはmanのどこにあるのかわかりませんでしたが、そういうものとして理解します。
rasum

2022/01/16 10:36

manのアドレス指定に関する \cregexpc が、「dコマンドで区切り文字をスラッシュにしない時は、先頭にバックスラッシュを付ける」ということなんでしょうね。
otn

2022/01/16 14:55

> manのアドレス指定に関する \cregexpc が、「dコマンドで区切り文字をスラッシュにしない時は、先頭にバックスラッシュを付ける」ということなんでしょうね。 そうです。 > 「区切り文字は何でもよい」というのはmanのアドレス指定に関する \cregexpc でしょうね。 失礼しました。sの区切り文字についてはman sedには明記されてないですね。info man には記述がありました。 info の日本語版は存在しないと思います。 > The '/' characters may be uniformly replaced by any other single character within any given 's' command.
guest

0

ルールはシンプルで、sの直後に書いた記号が「区切り文字」として扱われます。ただし\を書くと直後の文字の持つ「特別な意味」は失われて「普通の文字」となります。
s\/だと/は普通の文字列であって区切り文字になりません。これが「挙動の違い」の原因です。

投稿2022/01/16 06:52

KojiDoi

総合スコア13671

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

rasum

2022/01/16 09:19

KojiDoi様、ありがとうございます。 最初の区切り文字の直前にバックスラッシュを置くことは、置換のsでは、sの直後に区切り文字でなない普通の文字指定することになるので動作しないと理解しました。 スクリプトの末尾に書かれる、削除のdの場合は、最初の区切り文字の直前にバックスラッシュを置かないときちんと動作しないのがいまだ不明です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問