Linuxにおけるテキスト操作のためのSedストリームエディタの基本
紹介
sed コマンドは ストリームエディタ の略で、標準入力またはファイルからのテキストに対して編集操作を行います。 sed は行ごとに、かつ非対話的な方法で編集を行います。
これは、コマンドを呼び出すときにすべての編集決定を行い、sedが指示を自動的に実行することを意味します。これは混乱を招くまたは直感的でないように思えるかもしれませんが、特にスクリプトや自動化されたワークフローの一部としてテキストを変換する非常に強力で迅速な方法です。
このチュートリアルでは、基本的な操作のいくつかをカバーし、このエディターを操作するために必要な構文について紹介します。あなたはおそらく普段のテキストエディターを sed に置き換えることはないでしょうが、それはおそらくあなたのテキスト編集ツールボックスに歓迎される追加となるでしょう。
注意: このチュートリアルでは、Ubuntuやその他のLinuxオペレーティングシステムで見つかるGNU版のsedを使用します。macOSを使用している場合は、異なるオプションと引数を持つBSD版を使用しています。Homebrewを使用してgnu-sedのGNU版をインストールすることができます:brew install gnu-sed。
基本的な使用法
sed は、テキストファイルまたは標準入力 (STDIN) から読み取るテキストのストリームで動作します。これは、他のコマンドの出力を直接 sed に送信して編集することも、すでに作成したファイルで作業することもできることを意味します。
あなたは sed がデフォルトで全てを標準出力(STDOUT)に出力することも知っておくべきです。つまり、リダイレクトしない限り、sed はその出力をファイルに保存するのではなく、画面に表示します。
基本的な使用法は次のとおりです:
- sed [options] commands [file-to-edit]
このチュートリアルでは、BSDソフトウェアライセンスのコピーを使ってsedを試してみます。Ubuntuでは、次のコマンドを実行してBSDライセンスファイルをホームディレクトリにコピーし、作業できるようにします:
- cd
- cp /usr/share/common-licenses/BSD .
BSDライセンスのローカルコピーがない場合は、このコマンドで自分で作成してください:
- cat << 'EOF' > BSD
- Copyright (c) The Regents of the University of California.
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the University nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- SUCH DAMAGE.
- EOF
BSDライセンスファイルの内容を表示するためにsedを使用しましょう。sedはデフォルトで結果を画面に送信するため、編集コマンドを渡さずにファイルリーダーとして使用できます。次のコマンドを実行してみてください:
- sed '' BSD
画面にBSDライセンスが表示されます。
Copyright (c) The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
...
...
シングルクォートは、sedに渡す編集コマンドを含んでいます。この場合、何も渡さなかったので、sedは受け取った各行を標準出力に印刷しました。
sed はファイルではなく標準入力を使用できます。cat コマンドの出力を sed にパイプして、同じ結果を得ることができます:
- cat BSD | sed ''
ファイルの出力が表示されます:
Copyright (c) The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
. . .
. . .
ご覧のとおり、パイプ (|) 文字を使用して出力をパイプで接続する際に生成されるようなファイルやテキストのストリームに対しても、同じように操作することができます。
印刷ライン
前の例では、sedに操作なしで入力された場合、結果が標準出力に直接印刷されることを見ました。
「sed」の明示的な「print」コマンドを探求しましょう。これは、シングルクオート内で「p」文字を使用することで指定します。
次のコマンドを実行してください:
- sed 'p' BSD
あなたは各行のBSDファイルが2回印刷されるのを見るでしょう:
Copyright (c) The Regents of the University of California.
Copyright (c) The Regents of the University of California.
All rights reserved.
All rights reserved.
Redistribution and use in source and binary forms, with or without
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
modification, are permitted provided that the following conditions
are met:
are met:
. . .
. . .
sed はデフォルトで各行を自動的に印刷します。その後、あなたは “p ” コマンドで行を明示的に印刷するように指示したので、各行が2回印刷されます。
出力をよく見ると、最初の行が二回、次に二回目の行が続くなどしているのがわかります。これはsedがデータを行ごとに処理していることを示しています。行を読み取り、それに対して操作を行い、結果のテキストを出力してから、次の行でこのプロセスを繰り返します。
自動印刷を抑制するために、sedにオプション-nを渡すことで、結果をクリーンアップできます:
- sed -n 'p' BSD
Copyright (c) The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
. . .
. . .
私たちは今、各行を一度だけ印刷することに戻りました。
これまでの例は、編集と呼べるものではほとんどありません(各行を二回印刷したい場合を除いて…)。次に、sedがテキストデータの特定のセクションをターゲットにして出力を変更できる方法を探ります。
アドレス範囲の使用
アドレスは、テキストストリームの特定の部分をターゲットにすることができます。特定の行や行の範囲を指定することができます。
ファイルの最初の行をsedで表示させましょう。次のコマンドを実行してください:
- sed -n '1p' BSD
最初の行は画面に出力されます:
Copyright (c) The Regents of the University of California.
printコマンドの前に数字1を置くことで、sedに操作する行番号を指示しました。同様に、5行を印刷することもできます(“-n ”を忘れないでください):
- sed -n '1,5p' BSD
この出力が表示されます:
Copyright (c) The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
あなたはちょうどsedにアドレス範囲を与えました。sedにアドレスを与えると、その行に対してのみ、後に続くコマンドを実行します。この例では、あなたはsedに1行目から5行目を印刷するように指示しました。最初のアドレスを指定し、その後にオフセットを使用してsedに何行追加で処理するかを指示することで、別の方法でも指定できました。
- sed -n '1,+4p' BSD
これは同じ出力になります。なぜなら、あなたがsedに1行目から始め、次の4行にも操作を行うように指示したからです。
もし奇数行だけを印刷したい場合は、~文字の後に間隔を指定してください。次のコマンドは、BSDファイルの奇数行を、1行目から印刷します:
- sed -n '1~2p' BSD
こちらが表示される出力です:
Copyright (c) The Regents of the University of California.
modification, are permitted provided that the following conditions
1. Redistributions of source code must retain the above copyright
2. Redistributions in binary form must reproduce the above copyright
documentation and/or other materials provided with the distribution.
may be used to endorse or promote products derived from this software
. . .
. . .
sedを使用して、出力からテキストを削除することもできます。
テキストを削除する
以前テキストの印刷を指定していた場所で、p コマンドを d コマンドに変更することで、テキストの削除を行うことができます。
この場合、sedが削除されていないすべてのものを印刷するため、-nコマンドはもう必要ありません。これにより、何が起こっているのかを見る手助けになります。
前のセクションの最後のコマンドを修正して、最初の行から始まるすべての奇数行を削除するようにします:
- sed '1~2d' BSD
その結果、前回与えられなかったすべての行を見ることができます:
All rights reserved.
Redistribution and use in source and binary forms, with or without
are met:
notice, this list of conditions and the following disclaimer.
notice, this list of conditions and the following disclaimer in the
3. Neither the name of the University nor the names of its contributors
without specific prior written permission.
. . .
. . .
ここで注意することが重要なのは、ソースファイルが影響を受けていないことです。それはまだ intact です。編集内容は私たちの画面に出力されています。
編集を保存したい場合は、標準出力を次のようにファイルにリダイレクトできます:
- sed '1~2d' BSD > everyother.txt
今、catを使ってファイルを開いてください:
- cat everyother.txt
以前画面に表示されたのと同じ出力が表示されます:
All rights reserved.
Redistribution and use in source and binary forms, with or without
are met:
notice, this list of conditions and the following disclaimer.
notice, this list of conditions and the following disclaimer in the
3. Neither the name of the University nor the names of its contributors
without specific prior written permission.
. . .
. . .
デフォルトでは、sedコマンドはソースファイルを編集しませんが、-iオプションを渡すことでこの動作を変更できます。このオプションは「その場で編集を行う」という意味です。これによりソースファイルが変更されます。
警告:-iスイッチを使用すると元のファイルが上書きされるため、注意して使用する必要があります。最初に-iスイッチを使用せずに操作を実行し、必要な結果が得られたら再度-iを使ってコマンドを実行してください。元のファイルのバックアップを作成するか、出力をファイルにリダイレクトしてください。-iスイッチを使用すると、元のファイルを誤って変更してしまうことが非常に容易です。
作成したばかりの everyother.txt ファイルをそのまま編集してみましょう。さらに、再度偶数行を削除してファイルを減らしましょう:
- sed -i '1~2d' everyother.txt
catを使ってcat everyother.txtでファイルを表示すると、そのファイルが編集されていることがわかります。
-iオプションは危険です。幸いなことに、sedは編集する前にバックアップファイルを作成する機能を提供します。
編集する前にバックアップファイルを作成するには、「-i」オプションの直後にバックアップ拡張子を追加します:
- sed -i.bak '1~2d' everyother.txt
これにより、.bak 拡張子のバックアップファイルが作成され、その後元のファイルがその場で編集されます。
次に、sedを使用して検索と置換操作を実行する方法を見ていきます。
テキストを置き換える
sedの最もよく知られている使い方の一つは、テキストの置換です。sedは、正規表現を使用してテキストパターンを検索し、見つかったテキストを別のものに置き換えることができます。
Linuxでテキストパターンを検索するためのGrep正規表現の使用を追うことで、正規表現についてより多くを学ぶことができます。
最も基本的な形では、次の構文を使用して一つの単語を別の単語に変えることができます:
's/old_word/new_word/'
sは代替コマンドです。三つのスラッシュ(/)は異なるテキストフィールドを区切るために使用されます。もし他の文字がフィールドを区切るのにより便利な場合は、それを使用できます。
たとえば、ウェブサイトの名前を変更しようとしている場合、URLにスラッシュが含まれているため、別のデリミタを使用することが役立ちます。
次のコマンドを実行して、echoでURLを印刷し、アンダースコア(_)文字を区切り文字として使用してsedで変更します:
- echo "http://www.example.com/index.html" | sed 's_com/index_org/home_'
これは com/index を org/home に置き換えます。出力は修正されたURLを示しています:
http://www.example.org/home.html
最終デリミタを忘れないでください。さもなければsedは文句を言います。このコマンドを実行した場合:
- echo "http://www.example.com/index.html" | sed 's_com/index_org/home'
この出力が表示されます:
sed: -e expression #1, char 20: unterminated `s' command
いくつかの置き換えを練習するために新しいファイルを作成しましょう。以下のコマンドを実行して、song.txtという名前の新しいテキストファイルを作成します:
- echo "this is the song that never ends
- yes, it goes on and on, my friend
- some people started singing it
- not knowing what it was
- and they'll continue singing it forever
- just because..." > song.txt
それでは、式onをforwardに置き換えましょう。次のコマンドを使用してください:
- sed 's/on/forward/' song.txt
出力はこのようになります:
this is the sforwardg that never ends
yes, it goes forward and on, my friend
some people started singing it
not knowing what it was
and they'll cforwardtinue singing it forever
just because...
ここでいくつか注目すべきことが見えます。まず、sedは単語ではなくパターンを置き換えることです。songの中のonがforwardに変更されました。
もう一つ注目すべき点は、2行目で2番目のonがforwardに変更されなかったことです。
これは、デフォルトで、s コマンドが行内の最初の一致に対して操作し、その後次の行に移動するためです。sed が各行の最初だけでなく、on のすべてのインスタンスを置き換えるようにするには、置換コマンドにオプションフラグを渡す必要があります。
置換セットの後にgフラグを置くことで置換コマンドに提供します:
- sed 's/on/forward/g' song.txt
この出力が表示されます:
this is the sforwardg that never ends
yes, it goes forward and forward, my friend
some people started singing it
not knowing what it was
and they'll cforwardtinue singing it forever
just because...
今、置き換えコマンドはすべてのインスタンスを変更します。
もしあなたが各行で sed が見つける “on ” の第二のインスタンスだけを変更したいのであれば、g の代わりに番号 2 を使います:
- sed 's/on/forward/2' song.txt
今回は他の行は変更されていません。なぜなら、それらには二回目の出現がないからです。
this is the song that never ends
yes, it goes on and forward, my friend
some people started singing it
not knowing what it was
and they'll continue singing it forever
just because...
置き換えられた行だけを見たい場合は、自動印刷を抑制するために再度-nオプションを使用してください。
その後、pオプションを置換コマンドに渡すことで、置換が行われた行を印刷することができます。
- sed -n 's/on/forward/2p' song.txt
画面に出力を変更した行:
yes, it goes on and forward, my friend
ご覧の通り、コマンドの最後でフラグを組み合わせることができます。
検索プロセスに大文字と小文字を無視させたい場合は、“i ” フラグを渡すことができます。
- sed 's/SINGING/saying/i' song.txt
こちらが表示される出力です:
this is the song that never ends
yes, it goes on and on, my friend
some people started saying it
not knowing what it was
and they'll continue saying it forever
just because...
一致したテキストの置き換えと参照
複雑なパターンを正規表現で見つけたい場合、置換テキスト内で一致したパターンを参照するためのさまざまな方法があります。
例えば、行の先頭からatまで一致させるには、次のコマンドを使用します:
- sed 's/^.*at/REPLACED/' song.txt
この出力が表示されます:
REPLACED never ends
yes, it goes on and on, my friend
some people started singing it
REPLACED it was
and they'll continue singing it forever
just because...
ワイルドカード式は行の先頭から最後のatのインスタンスまで一致することがわかります。
検索文字列に一致する正確なフレーズがわからないため、置換文字列内で一致したテキストを表すために&文字を使用できます。
一致したテキストの周りに括弧を入れましょう:
- sed 's/^.*at/(&)/' song.txt
この出力が表示されます:
(this is the song that) never ends
yes, it goes on and on, my friend
some people started singing it
(not knowing what) it was
and they'll continue singing it forever
just because...
一致したテキストを参照するもっと柔軟な方法は、エスケープされた括弧を使用して一致したテキストのセクションをグループ化することです。
括弧で囲まれた検索テキストの各グループは、エスケープされた参照番号で参照できます。たとえば、最初の括弧グループは\1で、2番目は\2で参照できます。
この例では、各行の最初の二語を入れ替えます:
- sed 's/\([a-zA-Z0-9][a-zA-Z0-9]*\) \([a-zA-Z0-9][a-zA-Z0-9]*\)/\2 \1/' song.txt
この出力が表示されます:
is this the song that never ends
yes, goes it on and on, my friend
people some started singing it
knowing not what it was
they and'll continue singing it forever
because just...
ご覧のように、結果は完璧ではありません。たとえば、2行目は1語目をスキップしています。それは、私たちの文字セットに含まれていない文字があるためです。同様に、5行目ではthey'llを2語として扱いました。
正規表現をより正確にするために改善しましょう:
- sed 's/\([^ ][^ ]*\) \([^ ][^ ]*\)/\2 \1/' song.txt
この出力が表示されます:
is this the song that never ends
it yes, goes on and on, my friend
people some started singing it
knowing not what it was
they'll and continue singing it forever
because... just
これは前回よりずっと良いです。このグループは関連する単語と一緒に句読点を配置しています。
括弧内の表現を繰り返す様子に注目してください(最初は*文字なしで、次に*文字ありで)。これは、*文字がその前にある文字セットに対して0回以上の一致を示しているからです。つまり、ワイルドカードとの一致はパターンが見つからなくても「一致」と見なされます。
sed がテキストを少なくとも1回見つけることを保証するために、ワイルドカードを使用する前に、少なくとも1回はワイルドカードなしで一致させる必要があります。
結論
このチュートリアルでは、sedコマンドを探求しました。ファイルから特定の行を印刷し、テキストを検索し、行を削除し、元のファイルを上書きし、正規表現を使用してテキストを置き換えました。適切に構築されたsedコマンドを使用することで、テキストドキュメントを迅速に変換できることがすでにわかるはずです。
次の記事では、さらに高度な機能を探求します。
