sedを使って特定の文字列から文字列までを抜き出す

2 min read読了の目安(約1800字

やりたいこと

sedを使ってある文字列からある文字列までの間を抜き出したい。

サンプル

以下のようなテキストファイルがあり、## 昨日やったことから## 今日やることの間を抜き出す処理を書きたい。

2021/01/week_04/daily_20210127.md
## 昨日やったこと

- hoge
- fuga
- piyo

## 今日やること

・・・(省略)
$ sed -n "/## 昨日やったこと/,/## 今日やること/p" 2021/01/week_04/daily_20210127.md
## 昨日やったこと

- hoge
- fuga
- piyo

## 今日やること

→ これだと、開始文字と終了文字を含んでしまう。
以下のようにパイプで繋げて、開始文字・終了文字・空白行を削除すれば抜き出せました。

$ sed -n "/## 昨日やったこと/,/## 今日やること/p" 2021/01/week_04/daily_20210127.md \
| sed "/## 昨日やったこと\|^$\|## 今日やること/d"
- hoge
- fuga
- piyo

sedコマンド詳細

sedコマンドはStream Editorの略でエディタの一種。

sedコマンドイメージ図

コマンド形式

sed [オプション] コマンド・スクリプト 入力ファイル

オプション

  • -n・・・処理コマンド以外の標準出力を行わない

スクリプト・コマンド

前半部分

"/## 昨日やったこと/,/## 今日やること/p"
  • /## 昨日やったこと/,/## 今日やること/で、「昨日やったこと」の行から「今日やること」の行を対象を選択
  • pコマンドで上記で選択した結果を出力
  • 結果として以下が出力される
## 昨日やったこと

- hoge
- fuga
- piyo

## 今日やること

後半部分

"/## 昨日やったこと\|^$\|## 今日やること/d"
  • 前半部分で出力した文字列から「## 昨日やったこと」と「## 今日やること」、空白行を削除sています。
  • 空白行を正規表現で^$で表現
  • ポイントとして、正規表現の|がsedの特殊文字扱いになるのでバックスラッシュでエスケープする必要があります。
    • |^$|\|^$\|

ハマったポイント

上記の処理をスクリプト内で実行したところ、ターミナルから実行したときと結果が違ってしまう現象に遭遇してハマりました。原因はエイリアスはシェルスクリプト内ではデフォルトで機能しないため、ターミナルでの実行結果とスクリプト内での実行結果が違っていたためでした。
ちょうどGNUのsedを入れていたせい・・・

スクリプト内で以下を記述してエイリアスを有効にすればいいらしいのですが、うまく動かず・・・。

結果的にはスクリプト内ではgsedを使って対応しました。

参考