■ はじめに
https://dk521123.hatenablog.com/entry/2019/11/22/223043
で、sedコマンドを扱ったがかなり深いので、記事を分けた。 以下の動画で勉強するといいかも。
動画
https://dotinstall.com/lessons/basic_sed
目次
【1】sedコマンド 【2】Hello worldから概念を学ぶ 1)Hello World 2)解説 【3】使用上の注意 1)実行環境による差異 2)文字に「/」などが含まれている場合 【4】文法 1)オプション 2)アドレスの指定方法 【5】サンプル 例1:dコマンド : 1行目を削除 例2:pコマンド : 3行目だけ表示 例3:qコマンド : 3行以降は辞める 例4:iコマンド : 3行に「-------------」を挿入 例5:yコマンド : 文字置換(「-」=>「?」) 例6:sコマンド : 文字列置換 【6】実例 例1:改行コードの変換 CRLF => LF 例2:テンプレートファイルを書き換える 例3:文字列の抽出 例4:Trim処理 【7】おまけ:共通処理化
【1】sedコマンド
* sed (セド) : Stream EDitor * 文字列の置換/削除
【2】Hello worldから概念を学ぶ
* Hello World を使って、sedの概念を学ぶ * 以下のファイルを使う
hello.csv
id,name,remarks 001,Mike,- 002,Tom,Hello 003,Smith,World 004,Nick,!!
1)Hello World
# 3行目を消す sed -e "3d" hello.csv id,name,remarks 001,Mike,- 003,Smith,World 004,Nick,!!
2)解説
sed -e "3d" hello.csv [アドレス] [コマンド] 3(行目) d (delete:削除)
やってること
[1] ファイルから1行読み込んでパターンスペースに格納 (パターンスペース:メモリバッファ的なもの) [2] アドレスにマッチするか? => マッチした場合は、コマンドを実行 [3] パターンスペースを表示
【2】使用上の注意
1)実行環境による差異
* 実行環境(OS)によって動作や使える文法が変わる
2)文字に「/」などが含まれている場合
ダメ例:文字の置き換え
# 「/」が含まれている RELACED_PATH="/xxx/yyy/zzz.txt" # ${RELACED_PATH}内に「/」があるから、区切り文字と違いがわからない sed -e "s/__PATH__/${RELACED_PATH}/" template.txt > world.txt
対応案
区切り文字「/」を「|」にする
修正例
RELACED_PATH="/xxx/yyy/zzz.txt" # 区切り文字を「|」にする sed -e "s|__PATH__|${RELACED_PATH}|" template.txt > world.txt
参考文献
https://hacknote.jp/archives/8163/
【4】文法
1)オプション
# | オプション | オプション-フル(予想含む) | 説明 |
---|---|---|---|
1 | d | delete | 削除 |
2 | p | print? | 表示 |
3 | i | insert | 挿入 |
4 | a | append | 追加 |
5 | q | quit | 停止 |
6 | y | ??? | 文字置換 |
7 | s | string? | 文字列置換 |
2)アドレスの指定方法
1と3行目:「;」を使う
sed -e "1d;3d" hello.csv 001,Mike,- 003,Smith,World 004,Nick,!!
全行表示:「d」を使う
sed -e "d" hello.csv id,name,remarks 001,Mike,- 002,Tom,Hello 003,Smith,World 004,Nick,!!
【5】サンプル
例1:dコマンド : 1行目を削除
sed -e "1d" hello.csv 001,Mike,- 002,Tom,Hello 003,Smith,World 004,Nick,!!
例2:pコマンド : 3行目だけ表示
# -n : 出力コマンド以外の出力を行わない sed -n "3p" hello.csv
例3:qコマンド : 3行以降は辞める
sed -e "3q" hello.csv id,name,remarks 001,Mike,- 002,Tom,Hello
例4:iコマンド : 3行に「-------------」を挿入
# "【行数】u\【挿入したい内容】" sed -e "2i\-------------" hello.csv id,name,remarks ------------- 001,Mike,- 002,Tom,Hello 003,Smith,World 004,Nick,!!
例5:yコマンド : 文字置換(「-」=>「?」)
sed "y/-/?/" hello.csv id,name,remarks 001,Mike,? 002,Tom,Hello 003,Smith,World 004,Nick,!!
例6:sコマンド : 文字列置換
「00」=>消す
sed "s/00//" hello.csv id,name,remarks 1,Mike,- 2,Tom,Hello 3,Smith,World 4,Nick,!!
正規表現による置換
# "s/【正規表現】/【置換後の文字(&:正規表現で一致した文字)】/" sed -e "s/00[1-4]/<&>/" hello.csv id,name,remarks <001>,Mike,- <002>,Tom,Hello <003>,Smith,World <004>,Nick,!!
1行目を消す
# + 正規表現でIDとそれ以外に分けて、それ以外だけを表示する # (カッコは、バックスラッシュでバックスラッシュでエスケープ) sed -e "1d" -e "s/\(00[1-4]\),\(.*\)/\2/" hello.csv Mike,- Tom,Hello Smith,World Nick,!!
【6】実例
例1:改行コードの変換 CRLF => LF
sed "s/\r//g" win-newline.txt > unix-newline.txt
https://qiita.com/dharry/items/b4eead2868dddf1499f0
例2:テンプレートファイルを書き換える
# sed "s/正規表現/置換文字列/" テンプレートファイル > 置換後のファイル sed -e "s/__HELLO__/world/" template.txt > world.txt
template.txt
ここが、__HELLO__ に置き換わる
world.txt
ここが、world に置き換わる
例3:文字列の抽出
* 以下の関連記事を参照のこと。
シェル ~ 文字列抽出あれこれ ~
https://dk521123.hatenablog.com/entry/2021/08/03/160901
例4:Trim処理
https://genzouw.com/entry/2019/02/14/081819/850/
result="$(echo " abc def" | sed 's/^ *\| *$//')" echo "###${result}###" # <出力結果>###abc def###
【7】おまけ:共通処理化
https://dk521123.hatenablog.com/entry/2015/03/17/233124
で行った「別シェルの関数を呼ぶ」を使う
サンプル
util.sh
#!/bin/bash replace(){ old=${1} new=${2} input_file=${3} output_file=${4} sed -e "s|${old}|${new}|" ${input_file} > ${output_file} }
main.sh
#!/bin/bash . ./util.sh mkdir -p temp echo "1" replace '__IP_ADDR__' '127.0.0.1' 'template.tmp' 'temp/temp1.tmp' echo "return code : ${?}" echo "2" replace '__USER__' 'user001' 'temp/temp1.tmp' 'temp/temp2.tmp' echo "return code : ${?}" echo "3" replace '__PASSWORD__' 'passeword1' 'temp/temp2.tmp' 'output.conf' echo "return code : ${?}" rm -rf 'temp'
template.tmp
[localhost] __IP_ADDR__ [all:vars] ansible_ssh_user=__USER__ ansible_ssh_pass=__PASSWORD__
コマンド
$ ./main.sh 1 return code : 0 2 return code : 0 3 return code : 0
output.conf
[localhost] 127.0.0.1 [all:vars] ansible_ssh_user=user001 ansible_ssh_pass=passeword1
参考文献
https://www.atmarkit.co.jp/ait/articles/1610/17/news015.html
関連記事
awkコマンド
https://dk521123.hatenablog.com/entry/2019/11/22/223043
シェル 関数
https://dk521123.hatenablog.com/entry/2015/03/17/233124
JDBC を シェルスクリプトでパースする
https://dk521123.hatenablog.com/entry/2020/03/24/223323
シェル ~ 文字列抽出あれこれ ~
https://dk521123.hatenablog.com/entry/2021/08/03/160901
テキスト加工 ~ sed / awk ~
https://dk521123.hatenablog.com/entry/2019/11/22/223043