概略
grep: ファイルからマッチする行を取り出す.sed: 置換. インターネットで one-liners for sed などと検索する, 様々な処理を1行のsedスクリプトで行う例を多く見つけることができる.
正規表現
| grep | sed | awk | 意味 |
|---|---|---|---|
| . | . | . | 任意の 1 文字 |
| * | * | * | 直前の 1 文字または 1 パターンの 0 回以上の繰り返し |
| ^ | ^ | ^ | 行の先頭 |
| $ | $ | $ | 行の末尾 |
| \( \) | \( \) | ( ) | パターンのグループ化 |
| \1 \2 \3 | \1 \2 \3 | 後方参照 | |
| [] | [] | [] | 括弧内の任意の 1 文字 |
| \{n, m\} | \{n, m\} | {n,m} | 直前の 1 文字または 1 パターンの n 回以上かつ m 回以下の繰り返し |
| \{n, \} | \{n, \} | {n, } | 直前の 1 文字または 1 パターンの n 回以上の繰り返し |
| \{n\} | \{n\} | {n} | 直前の 1 文字または 1 パターンの n 回の繰り返し |
| \+ | \+ | + | 直前の 1 文字あるいは 1 パターンの 1 回以上の繰り返し |
| \? | ? | 直前の 1 文字あるいは 1 パターンの 0 回または 1 回だけ出現 | |
| \| | \| | \ | 2 パターンのうちどちら片方 |
正規表現
.任意の1文字を表す.
ワイルドガードという.
.*
任意の0文字以上を表す.
シェルでは正規表現と異なり, *だけなので注意が必要.
[...]
文字クラスという.括弧内に記述した文字にマッチする.
例) [Ww]hat -> What, what.
H[12345] -> H1, H2, H3, H4, H5
注意: 括弧内では, ワイルドガードなどの特殊な意味は無効になる.
括弧自体を探すときは, [a\]1]とエスケープシーケンスが必要.
[A-Z]
全てのアルファベット
[0-9]
全ての数字
例) [cC]hapter[1-9] -> Chapter3やchapter7など. Chapter1に該当してChapter12が含まれるぶんが抜き出されることがある. 一桁だけとマッチするようにしたければ, [cC]hapter[1-9][^1-9]とする.
[0-9a-z?,.;:'"]
複数の範囲もOK.
[-+*/]
マイナス記号をマッチさせたければ, 一番最初に書くといい.
20[0-9][0-9][-/][0-9][0-9][-/][0-9][0-9]
-> 2021/03/12, 2021-04-28など日付とマッチするものとマッチする.
[^0-9]
^はマッチ除外. 0-9以外の文字とマッチする.
[^aiueo]
母音以外とマッチ.
[[.ch.][.CH.]]
照合記号[.と.]で囲まれるとそれを一文字のように扱う.
chかCHを含むchapterやCHAPTERなどとマッチする.
*
直前の文字0回以上の繰り返し.
例) "*hyper"* -> hyper, "hyper", ""hyper"""""など.
[15]00*
-> 10, 50, 100など. 0が1回以上.
1回以上の繰り返しにしたい時は, 2回書くといい.
+
1回以上の繰り返し.
[15]0+は前述の意味と同じ.
<.*>
htmlのタグにマッチ.
can[ no']*t
cannot, can not, can't, cantに一致.
?
0回か1回の繰り返し.
80[234]?86
-> 8086, 80286, 80386, 80486.
シェルの?は正規表現の.であるので注意.
位置を表すメタキャラクタ
^hoge.^は行頭を表す.
.*$
$は行末を表す.
grep -c '^$' hoge.txt
-cをつけてカウントする.
^$は空行にマッチする.
grep -c '^ *$' hoge.txt
空白が入っている空行もカウント.
文字の繰り返し
\{n,m\}n回からm回までの任意の繰り返し. ただしn,mは0から255までの整数.
10\{2,4\}1 -> 1001, 10001, 100001.
[0-9]{\3}-[0-9]{\4}
郵便番号000-0000
[0-9][0-9]*\.\{5,\}[0-9][0-9]*
コンマをつけると以上になる.
1.....5
5000.........1330
Lab(oratorie)?s
()は正規表現をグループ化する.
compan(y|ies)
選択演算子 |
ch|CHchかCHにマッチ.
grep
grep
grepはedのg/re/pに対応している.コマンドラインから正規表現を受け取って, 表示する.
【 grep 】コマンド――特定の文字を含む行を抽出する
grep [オプション] 検索パターン ファイル
マークアップ言語のタグの取り出し.
grep '<.*>' hoge.txtsed
sed
置換して, 全ての行を表示する.sed [-e] 'instruction' file
sed 's/MA/Massachusetts/' hoge.txt
複数の命令をするとき,
sed 's/ MA/, Massachusetts/; s/ PA/, Pennsylvania/' hoge.txt
sed -e 's/ MA/, Massachusetts/' -e 's/ PA/, Pennsylvania/' hoge.txt
sed 置換した行だけ表示
sed -n -e 's/MA/Massachusetts/p' hoge.txt単純置換プログラム gres
if [ $# -lt "3" ]then
echo 'Usage: gres pattern replacement file'
fi
pattern=$1
replacement=$2
if [ -f $3 ]
then
file=$3
else
echo "$3 is not a file"
exit 1
fi
A='/'
sed -e "s$A$pattern$A$replacement$A" $file
sed
1. 行を指定しない限り, 標準として全ての行に適応される.2. 元のファイルは変更されない.
3. 最初の行に全てのコマンドが適応され, 次の行に全てのコマンドが適応され...のように実行されていく. このお陰でいかに大きなファイルでも処理することができる.
4. 元のファイルは変更されないが, 逐次的に処理していくときの途中では処理されたものを入力として次の処理を行う.
例) pig cow horse
sed -e 's/pig/cow/' -e 's/cow/horse/'
> cow cow horse
>horse horse horse
sed
sed 's/CA/California/g' hoge.txtファイルに含まれているCAを全てCaliforniaにswapする. 結果は含まれていない行も含めて全て表示.
sed '/Sebastopol/s/CA/California/g' hoge.txt
Sebastopolが含まれる行でCAを全てCaliforniaにswapする. 結果は含まれていない行も含めて全て表示.
d
全ての行を削除
1d
1行目を削除.
$d
最終行を削除
/^$/d
空行を削除する. 正規表現は/と/で囲まなければならない.
50,$d
50行目から最終行まで削除.
/^\.TS/,/^\.TE/d
sed では「.」をコンマとして使いたい場合/と/の中をエスケープする必要がある.
.TSと.TEで囲まれる部分を削除. .TSと.TEが含まれる行ごと削除される.
sed '/^\.TS/,/^\.TE/d' hoge.txtのようにして使うと''はシェルに解釈されないためのシングルクオーとであり, sedに対してはクオートされないので''中でクオートしても問題なし.
1,/^$/d
1行目から最初に登場する空行を削除.
これはファイルのヘッダーを取り除く時に便利.
/^\.TS/,/^\.TE/!d
!をつけるとマッチの意味が反対になる.
/^\.TS/,/^\.TE/{
/^$/d
/田中/d
}
.TSと.TEで囲まれる部分のうち, 空行と田中が含まれる行を削除. .TSと.TEが含まれる行ごと削除される.
sedは結果を標準出力するだけなので, ファイルにしたければリダイレクションする.
元のファイルが必要なければmv newfile oldfileのようにoldfileにnewfileを上書きするといい.
s/^ *//
スペースを2つ入れている. 全ての行の先頭の空白を取り除く.
s/ */ /g
全ての行の連続するスペースを1つのスペースに変更する.
s/\. */\. /g
ピリオドの後の空白を2つにする. sedとは関係ないが, ピリオドの後の空白は一般的に1つ.
runsedというコマンドを作成する.
カレンとディレクトリにsedscr, hoge.txt, hoge1.txtが存在する.runsed hoge.txt hoge1.txtなどと使用すると,
hoge.txtの内容に変更が存在すれば, bak.hoge.txtなどを作成し, 元のファイルが変更される.
変更がなければ, 標準出力にfile not changed: と表示される.
#! /bin/bash
for x
do
echo "editing $x: "
if test "$x" = sedscr; then
echo "not editing sedscript!"
elif test -s $x; then
sed -f sedscr $x > /tmp/$x$$
if test -s /tmp/$x$$
then
if cmp -s $x /tmp/$x$$
then
echo "file not changed: "
else
mv $x bak.$x #念の為オリジナル保存
cp /tmp/$x$$ $x
fi
echo "done"
else
echo "Sed produced an empty file"
echo "- check your sedscript."
fi
rm -f /tmp/$x$$
else
echo "origenal file is empty."
fi
done
echo "all done"
POSIX
[:alnum:] 印字可能な文字(空白文字を含む)[:print:] 印字可能な文字(空白文字を含む) [:graph:] 印字可能な文字(空白以外)
[:alpha:] アルファベット文字
[:blank:] スペースとタブ
[:ctrl:] 制御文字
[:digit:] 数字
[:lower:] 小文字
[:upper:] 大文字
[:punct:] 句読文字
[:space:] スペース
[:xdigit:] 16進数
sedでもgrepのようなことができる.
sedでもgrepのようなことができるが, 出力する前に入力を変更できるというメリットがある.sed -n "/^\.deBL/,/^\.\.$/p" /usr/lib/macros/mmt
先頭が.deBLで始まる行から, 先頭が..で始まる行までを取り出す.
例)
.deBL
hoge hoge hogehoge
hoge hoge hogehoge
hoge hoge hogehoge
..
-nオプションはsedを表示コマンドで指定したものだけを表示する.
2つのアドレス/^\.deBL/と/^\.\.$/は表示コマンドpが適応する行の範囲を指定している.
sed LaTex用アウトライン生成
情報を読みやすくするスクリプトsed -n'
s/[{}]//g
s/\\section/■A./p
s/\\subsection/■■B./p' $*
sed
--は「(em」に置換されて, ---は置換されない.sed '/---/!s/--/\\(em/g' file
sedの4箇条
1. 汝の入力をしれ.- grepを使って自分の入力ファイルを慎重に調べること.
2. 買う前に試食せよ.
3. 飛ぶ前に見ろ.
4. 現実的であれ.
- 手動で行った方が早いこともある.
sed
[adress]s/pattern/replacement/flagsn: 数字1~512を指定すると, 1行の中でマッチするn番目のパターンだけが置換される.
g: パターンスペース中でマッチするもの全てをグローバルに変更する.
p: パターンスペースの内容を表示する.
w file_hoge.txt: パターンスペースの内容をfile_hoge.txtに書き出す.
説明: adressにマッチする行に適応する.adressが指定されていなければ, 全ての行に置換が実行される. flagにgを指定しないと最初にマッチした行しか置換されない. pやwは-nオプションが指定されているときに用いる.
改行で置換する
sed '/^.Ah/{
s/\.Ah */\
\
@A HEAD = /
s/"//g
s/$/\
/
}' hoge.txt
.Ah "Major Heading"
->
改行
改行
@A HEAD = Major Heading
改行
に変換.
&
アンパサンドという.
patternを表す.
s/UNIX/\\s-2&\\s0/g
&はUNIXを表すので, UNIX
->
\s-2UNIX\s0と置換される.
s/See Section [0-9][0-9]*\.[0-9][0-9]*/(&)/g
See Section 12.4を(See Section 12.4)に置換する.
s/\(See Section \)\([0-9][0-9]*\.[0-9][0-9]*\)/\1\\fB\2\\fP/g
エスケープ付き括弧で正規表現の任意の部分を囲めば, それをセーブしておいてあとで使える.
\1, \2のようにして使うことができる.9つまでセーブできる.
->
See Section \fB12.9\fP
例2)
sed 's/\(.*\):\(.*\)/\2:\1/' hoge.txt
first:second
->
second:first
sed 追加, 挿入, 変更
[line-adress]a\text
[line-adress]の後に追加
[line-adress]i\
text
[line-adress]の前に挿入
[adress]c\
text
変更
/abcdef/i\
ghijk\
lmnopr
abcdefにマッチした行の前に2行ghijk, lmnoprを挿入
/^From /,/^$/c\
<Mail header Remove>
Fromで始まる行から, 次の空行までを<Mail header Remove>に変更する.
1i\
abcde\
fghijk
1行目の前に2行を追加.
sed 変換
単語ではなく, 文字を置き換える.y/abcdefghijkl/ABCDEFGHIJKL/
これを使えば,
abbbbcff
->ABBBBCFF
のように順番通りではなくても, 一文字一文字が変換される.
表示コマンドp
パターンスペースの内容を表示する.表示コマンドはデバック用に使える.
表示フラグ(/p)と表示コマンド(単体)の違いは, 前者は置換が成功した場合だけ表示すること.
/^\.Ah/{
p
s/"//g
s/\.Ah //p
}
まず何も施していないものを出力. 次に"を削除, その次に.Ahを削除.
行番号の表示
adressの前に=を入れると, マッチした行の行番号が表示される.行の自動出力を抑制しなければ, 行番号と行自体の両方が表示される.
/■if{
=
p
}
■はタブを表す.
行番号, 改行, 1行.
sed 次行読み込み
文字列.H1で始まる全ての行を見つけ, その行を表示して次の行を読み込む. 読み込んだ行が空行だったら削除する./^\.H1/{
n
/^S/d
}
sed ファイルの読み書き
読み込み
[line-adress]r file一つのスクリプトについてオープンできるファイルは10個
/^Company_list/r company.txt
Company_listで始まる行とマッチしたら, company.txtというファイルの内容を追加する.
注意)この後にあるコマンドは, ファイルから読み込んだ行には作用しない.
sed '$r closing.txt' $*
引数に指定した全てのファイルに対し, closing.txtの文章をファイルの最後に追加する.
書き込み
Tanaka JapanYamada America
Hiraoka China
Akazaki Japan
国名の担当者だけ取り出す.
/Japan$/w region_Japan.txt
/America$/w region_America.txt
/China$/w region_China.txt
ファイルに書き出す前に国名を取り除いてしまいたい時は
/Japan$/{
s///
w region_Japan.txt
}
awk
awk 'instruction' filesawk 各行の1単語めだけ書き出す.
awk '{print $1}' hoge.txtawk パターンにマッチした行だけ書き出す.
awk '/MA/' hoge.txtawk パターンにマッチした各行の1単語目だけを書き出す.
awk '/MA/ {print $1}' hoge.txtawk フィールドセパレータをスペースではなく, コンマに変える.
awk -F, '/MA/ {print $1}' hoge.txtFは大文字でないといけない.
awk 各行の3単語目までを行を変えて表示
hoge.txtの内容1 2 3 ...
4 5 6 ...
7 8 9 ...
awk '{print $1; print $2; print $3 }' hoge.txt
出力
1
2
3
4
5
6
7
8
9
awkスクリプトの書き方
echo 'Hello world' > test.txtawk '{ print }' test.txt
>Hello world
awk '{ print aiueo }' test.txt
> aiueo
awkは入力駆動型であり, test.txtの1行ごとに実行される. printの後に何も書かなければ, test.txtの内容が全て書き出される. print aiueoとした場合, test.txtが複数行あれば, 複数回aiueoが表示される.
awkに入力を与えずに表示する.
awk 'BEGIN { print "Hello world" }'BEGINは入力1行目が読み込まれる前に実行するアクションを指定したい時に使う.
全ての行の処理が終わった後に実行
awk 'END { print "Hello world' } text.txt入力行が空行だったら, "This is a blank line."を表示
awk '/^$/ { print "This is a blank line." }'レコードとフィールド
