質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

sh

shは、UNIX系OSのシェル操作の1つであり、最も基本的なシェルのことです。

Q&A

解決済

2回答

981閲覧

文字列置換・挿入について

kty_kk

総合スコア4

bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

sh

shは、UNIX系OSのシェル操作の1つであり、最も基本的なシェルのことです。

0グッド

0クリップ

投稿2021/06/21 08:58

編集2021/06/22 11:06

bashにて置換・挿入を行えるツールを作成したいと考えています。
ツールイメージは下記です。
①指定パス配下(サブディレクトリも含む)存在するファイルをパスごと取得し、テキストファイルに1行ずつリスト化するよう出力する。
→find パス名 -print >>list.txt
➁for文を使用し、①でリスト化(list.txt)に記載のあるパス+ファイル名を読み取り、全ての指定した置換対象文字列の前後行に指定の文字列挿入
③置換対象文字列を全て置換

現在記載しているコードは以下です。(序盤省略)

bash

1#!/bin/sh -f 2 3#$1置換対象とするファイルが存在する場所を指定 4#$2置換対象とする文字列 5#$3置換後の文字列 6 7~~~省略~~~ 8find $1 -print >>list.txt 9 10for file in `cat list.txt` 11do 12 sed `/$2/s/^/[前行用挿入文字列] $file &&/ 13 sed `/$2/s/$/[後行用挿入文字列] $file &&/ 14 sed `s/$2/$3/g` $file>$file.bak 15done

▲問題・改善したい内容
①sedコマンドを使用する際、行末に&&/を使用している。
⇒仮に置換対象ファイルに3つの置換対象文字列が存在した場合、3つの文字列に対してそれぞれ挿入・置換を行いたいがために
記載をしてみたが思うようにいかない。

➁置換前文字列と置換後文字列を引数で実施している。
⇒1つのファイルに対して複数パターンの文字列を置換したい場合がある。
そのため更にfor文等を使用・及び、置換前文字・置換後文字リストを予めテキストファイル等に用意し
リストに記載のある置換パターンを全て実施できるようにしたい。

現状としてシェルを独学で学習(本・インターネット)し、記載してみたが手詰まり…という形です。
プログラミング自体初心者ではありますが、ご回答いただけると幸いです。

●補足(置換・挿入イメージ)
例)置換対象ファイル内容
aaa
bbb
ccc
ddd
eee

置換&挿入後(bbbが置換対象文字列とし、bbb前後行に文字列(下記例だと「~挿入及び置換Start~と~挿入及び置換End~」)を挿入しbbbをzzzに置換)
aaa
~挿入及び置換Start~
zzz
~挿入及び置換End~
ccc
ddd
eee

という形にしたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

実行環境の問題だったため、環境を変更したら解決いたしました。

投稿2021/07/07 06:28

kty_kk

総合スコア4

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

①sedコマンドを使用する際、行末に&&/を使用している。

sedを3回使っていますが、最初の2回で置換結果を書き出していないので、意図している文字列の挿入は実現しないでしょう。sedのスクリプトを一つにまとめる必要がありそうです。

また、

sed `s/$2/$3/g` $file>$file.bak

では新しい内容の方が$file.bakになってしまいます。ここはsedのiオプションを使うべきでしょう。

質問文からは「挿入文字列」の挿入規則が今ひとつよく分からないのですが、かりに「置換すべき文字列を含む行をマーカー的な行で挟みたい」ということだとすると、sed部分は以下のような感じではないかと思います。

sed -i.bak 's/^.*置換前文字列.*$/前行用挿入文字列&後行用挿入文字列/; s/置換前文字列/置換後文字列/'

次にfindですが、ファイルのリストを別のところで利用するのでなければ、わざわざ中間ファイルに書き出す必要はなさそうです。

find -exec sed -i.bak sedスクリプト {} \;

実際にはtarget, replaceに/"が入ったときの対処とかも考えておく必要がありそうですが、とりあえず措いておくとすると、スクリプトはこんな感じになるのではないでしょうか。

#!/usr/bin/bash dir=$1 target=$2 replace=$3 find ${dir} -exec sed -i.bak "s/^.*${target}.*$/前行用挿入文字列\n${replace}\n後行用挿入文字列/" {} \;

投稿2021/06/21 16:06

KojiDoi

総合スコア13692

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kty_kk

2021/06/22 11:20

ご回答ありがとうございます。 補足欄に実行後のイメージ図を記載いたしました。 回答に記載いただいた find ${dir} -exec sed -i.bak "s/^.*${target}.*$/前行用挿入文字列\n${replace}\n後行用挿入文字列/" {} \; というのは  ・${dir}(実行第一引数)に置換対象があるパス  ・${target}(実行第二引数)に置換対象文字列 ・${replace}(実行第三引数}に置換後文字列 ・前行用挿入文字列に 補足欄でいう~挿入及び置換Start~ ・後行用挿入文字列に 補足欄でいう~挿入及び置換End~ という認識であっておりますでしょうか。 実行ファイルをtikan.sh 置換対象ファイル(aaa bbb ccc ddd eeeと記載)をtest.txtとし 『●/●/…⇒検索対象配下{dir} aaa⇒{target} zzz⇒{replace} 前行用挿入文字列⇒~挿入及び置換Start~ 後行用挿入文字列⇒~挿入及び置換End~』 ↓実行 ./tikan.sh ●/●/… aaa zzz ~挿入及び置換Start~ ~挿入及び置換End~ で実行した所、 aaa bbb ccc ddd eee #!/bin/sh dir=$1 target=$2 replace=$3 ~挿入及び置換Start~nzzzn~挿入及び置換End と表示されただけなのですが、実行方法が誤っているのでしょうか。 ※sedの-iコマンドが私の環境で実行されず、『オプションが正しくありません』と出てしまうため、一旦付けていないのですがこれが問題でしょうか。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問