Typoしたものが大半なのだけど、指定した文字列とN文字違ったり、1文字ずれている(「あい
うえお」→「いあ
うえお」みたいな)文字列をヒットさせたいということがごくごくたま~にあって、それをgrepでときどきやっている。
個人のマシンではfunctionを作ってあるのだけど、たま~にリモートマシンで使うとき(+ローカルのrcファイルを読み込ませてない時)なんかにはその場でコマンドを組み合わせたりしているので、備忘で残しておく。
1文字違う文字列をgrepする
指定した文字列から1文字違う文字列をgrepする場合、以下のようにする。
echo 検索対象文字列 | grep -f <(echo 検索文字列 | grep -o . | awk '{a=$0=a$0}END{for(i=1;i<=NR;i++){print gensub(/./,".",i)}}')
blacknon@BS-PUB-UBUNTU-01:~$ echo これはあいんえお | grep -f <(echo あいうえお | grep -o . | awk '{a=$0=a$0}END{for(i=1;i<=NR;i++){print gensub(/./,".",i)}}')
これはあいんえお
何しているのかを簡単に記述したのが以下。
# grep -f <()で、()内で生成した文字列をファイルとして読み込ませる
grep -f <(
echo 検索文字列 | \
# 検索文字列を1文字づつに分解 \
grep -o . | \
# 各文字が「.」の組み合わせを生成(「あいう」→「.いう」「あ.う」「あい.」) \
gawk '
{a=$0=a$0}
END{
for(i=1;i<=NR;i++){
print gensub(/./,".",i)
}
}'
)
1文字ずれている文字列をgrepする
似たようなやり方で、1文字ずれている文字列についてもgrepを行える(Macの場合はgsedを使う必要あり)。
echo 検索対象文字列 | grep -f <(STR="検索文字列";for i in $(seq 0 $((${#STR}-1)));do sed -r 's/(.{'$i'})(.)(.)/\1\3\2/' <<<$STR;done)
blacknon@BS-PUB-UBUNTU-01:~$ echo うんこ | grep -f <(STR="うこん";for i in $(seq 0 $((${#STR}-1)));do sed -r 's/(.{'$i'})(.)(.)/\1\3\2/' <<<$STR;done)
うんこ
これも、何をしているのかを一応コメント付きのものを載せておく。
# grep -f <()で、()内で生成した文字列をファイルとして読み込ませる
grep -f <(
STR="検索文字列"
# forで文字列の位置を1文字ずつずらす
for i in $(seq 0 $((${#STR}-1)));do
# sedで$i分だけ文字列を無視して置換(\2と\3の位置をずらす)
sed -r 's/(.{'$i'})(.)(.)/\1\3\2/' <<<$STR;
done
)
どちらも一発で検索させる
どちらも一発で出す場合、ちょっと乱暴だけど以下のようにしとけばいい。 (ちゃんと書くなら変数にしてfunctionにしたほうがいいと思うけど…(´・ω・`))
echo 検索対象文字列 | grep -f <(cat <(STR="検索文字列";for i in $(seq 0 $((${#STR}-1)));do sed -r 's/(.{'$i'})(.)(.)/\1\3\2/' <<<$STR;done) <(echo 検索文字列 | grep -o . | awk '{a=$0=a$0}END{for(i=1;i<=NR;i++){print gensub(/./,".",i)}}'))
blacknon@BS-PUB-UBUNTU-01:~$ echo これはあたうえお | grep -f <(cat <(STR="あいうえお";for i in $(seq 0 $((${#STR}-1)));do sed -r 's/(.{'$i'})(.)(.)/\1\3\2/' <<<$STR;done) <(echo あいうえお | grep -o . | awk '{a=$0=a$0}END{for(i=1;i<=NR;i++){print gensub(/./,".",i)}}'))
これはあたうえお
functionにしたものはここにおいてあるので、もし使う場合はそれを利用するといいだろう。