
お世話になります。
現在テキスト・エディターで文字列の置換作業を行っております。
エディターで置換を行った後に、ターミナルで特定文字列の抽出作業を行っているのですが、文字列置換作業もターミナルから行う事ができれば、文字列置換と文字列抽出の一連の作業を全てターミナルで行う事が出来るため、可能であれば文字列置換もターミナルから行いたいと思っております。
現在エディターで行っている置換内容は下記の通りになっております。(正規表現利用)
/test/(apple.*?)/
↓
\n\1\n
※「/test/(apple.*?)/」を「\n\1\n」に置換すると言う意味です。
これをターミナルコマンドから該当ファイル(ファイル名は「wordtest1.txt」)内の文字列を一括で置換するには、どのように記述すれば良いでしょうか?
置換後は別名ファイルで保存したいと思っています。
元ファイル「wordtest1.txt」を読み込んで文字列置換を行い、「wordtest2.txt」として保存。
お力を貸して頂ければ助かります。
よろしくお願い致します。
No.2ベストアンサー
- 回答日時:
perl には s/// による置き換えがあります。
これは エディタの置換機能に対応させると
s/検索パターン/置換文字列/
となります。パターンや置換文字列に / を含む場合、 パターン中の / を \/と書くか、区切り用の文字を / から別の文字に変えるかします。
正規表現は言語、コマンド等によって違うので注意しましょう。
よりくわしくは、PerlDoc 等を参考にしてください。
http://perldoc.jp/docs/perl/5.18.1/perlretut.pod
http://perldoc.jp/docs/perl/5.14.1/perlre.pod
おまけ:
○連続してコマンドを実行する方法:
→シェルスクリプトを使います。例えば
perl -npe 's|/test/(apple.*?)/|\n$1\n|;' wordtest1.txt > wordtest2.txt
grep -o ^apple.*$ wordtest2.txt > wordtest3.txt
awk '!a[$0]++' wordtest3.txt > wordtest4.txt
というファイル wortest.sh を作って
sh wordtest.sh
で連続で行えます。
→ コマンドを ; で区切ると、1行で書いたものを連続で実行します
perl -npe 's|/test/(apple.*?)/|\n$1\n|;' wordtest1.txt > wordtest2.txt ; grep -o ^apple.*$ wordtest2.txt > wordtest3.txt ; awk '!a[$0]++' wordtest3.txt > wordtest4.txt
→ 中間ファイル (wordtest2.txt, wordtest3.txt)が不要なら、パイプが使えます。
パイプは前段の標準出力と後段の標準入力を継げます
perl -npe 's|/test/(apple.*?)/|\n$1\n|;' wordtest1.txt grep -o '^apple.*$' | awk '!a[$0]++' > wordtest4.txt
→ 並び順が変ってよいのなら、 awk の部分は sortコマンドの -uオプションが使えます。
→ 3つの内容をperlで一つに纏めることができます。
kmee様、ご教授ありがとうございます。
perl -npe 's|/test/(apple.*?)/|\n$1\n|;' wordtest1.txt > wordtest2.txt ; grep -o ^apple.*$ wordtest2.txt > wordtest3.txt ; awk '!a[$0]++' wordtest3.txt > wordtest4.txt
上記の記述をwordtest.shに記述して「sh wordtest.sh」として実行したら上手く出来ました(^-^)
あと1つコマンドを追加したいと思ったのですが、上手く出来なかったためご教授頂ければ助かります。
「wordtest1.txt」についてですが、これは複数のファイルを結合して作成したファイルなのですが、この結合作業も一緒に行えたら良いと思っております。
現在は「cat test/* > wordtest1.txt」と打ち込んで実行して、「test」フォルダの中のファイルを全て結合して「wordtest1.txt」を作成しております。
; で区切ると連続で実行できると言うことだったので、下記のように記述して実行してみましたが上手く出来ませんでした。
cat test/* > wordtest1.txt ; perl -npe 's|/test/(apple.*?)/|\n$1\n|;' wordtest1.txt > wordtest2.txt ; grep -o ^apple.*$ wordtest2.txt > wordtest3.txt ; awk '!a[$0]++' wordtest3.txt > wordtest4.txt
アドバイスをお願い致します。
No.5
- 回答日時:
#2に書いたURL や
http://perldoc.jp/docs/perl/5.20.1/perlop.pod#Re …
「Perl 正規表現 置換」等で調べてみてください。
s|/test/(apple.*?)/|\n$1\n|g
と、gオプションを付けることで、1行に複数あった場合にその全てが対象になります。
どのエディタを使っているかがわかりませんが。
現在なら、無難なのはUTF-8だと思います。
No.4
- 回答日時:
バックスラッシュと円記号にはややこしい歴史がありまして。
正しくASCIIコード0x5cのバックスラッシュでないと、プログラムとしては期待した動作をしてくれません。
od -t x1c wordtest.sh
で、各文字の文字コード付きのダンプリストが出力されます。
これで、バックスラッシュの上がどうなっているか、確認してください。
5cになっていなかったら、5cになるように工夫が必要です。
Option+\で入力してみるとか
保存に使ったエディタで、文字コードを変えてみるとか。
アドバイスありがとうございます。
od -t x1c wordtest.sh
上記を実行したところ、逆スラッシュが「200」と表示され「200」の上は「80」になっていました。
wordtest.shのエンコードをエディタで「windows,DOS」に変更したら、逆スラッシュとなり上には5cと表示されるようになりました。
これでwordtest.shを実行した所、最後までコマンドを実行する事が出来るようになりました。
ご指摘通りファイルのエンコード形式に問題があったみたいですね。
「Unicode UTF-8」「ISO 2022-JP」も同様に逆スラッシュ(5c)になりましたが、どのエンコード形式が無難なのでしょうか?
また1つ問題が出てきしてしまい、最後までコマンドは実行されて結果も出力されるのですが、エディターを使った場合と結果が異なってしまっています。
コマンドを1つ1つ実行して確かめた所、perlのコマンドの所で問題がありそうです。
perl -npe 's|/test/(apple.*?)/|\n$1\n|;' wordtest1.txt > wordtest2.txt
上記コマンドを実行した結果のwordtest2.txtをエディターで開いて、「/test/(apple.*?)/」で検索すると全ての該当箇所が置換出来ていないようです。
エディターを使用した場合では、全て置換する事が出来ています。
考えられる原因は分かりますでしょうか(>_<)
No.3
- 回答日時:
○ ; て継ぐのは、1行で書くためのものです。
ターミナルでコマンド入力するときとか。
ファイルに保存して実行させる場合には、1行に1コマンド書けば、 ; は不要です。
cat test/* > wordtest1.txt
perl -npe 's|/test/(apple.*?)/|\n$1\n|;' wordtest1.txt > wordtest2.txt
grep -o '^apple.*$' wordtest2.txt > wordtest3.txt
awk '!a[$0]++' wordtest3.txt > wordtest4.txt
○ ^apple.*$ のような文字列をそのまま書くと、*とか$とかがシェルで展開されることもあります。
引用符でくくる等するのがよいでしょう。
○「うまくいかない」だけだと判断しかねます。
・なにかエラーになっているなら、そのエラーを書く
・せっかく中間状態がファイルに残っているのですから、どのファイルが期待と違う調べる。
そうすれば、どこに間違いがあるかの目安になる。
・sh -x wordtest.sh
と-xオプションを付けると、実際に実行する内容が出力されるので、期待通りになっているか確認する
No.1
- 回答日時:
MacOSのターミナルでは、UNIX標準のものが使えます。
定番は sed
https://developer.apple.com/library/mac/document …
ただ、 *?はそのままsedでは使えないので、正規表現の機能が豊富な perl で「ワンライナー」というのがいいかもしれません。
ご回答ありがとうございます。
プログラムの知識がほとんど皆無のため、具体的にどのように記述すれば良いのかご教授頂ければ助かります。
よろしくお願い致します。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) EXCEL VBA 単語置き換え について質問です ブック名 ぶぶぶ シート名 ししし セル V3〜 3 2023/03/08 01:41
- Visual Basic(VBA) 特定の文字を簡単な操作で半角スペースに変換するか削除したい 2 2022/11/01 10:35
- フリーソフト フォルダ、ファイル名の一括変換について 3 2023/03/16 09:23
- Visual Basic(VBA) Excel VBAでAA(BBB) → BBB.AA に置換したい 2 2022/10/30 13:59
- Visual Basic(VBA) Excel VBA 教えてください。 VBA初心者です。 詳しい方がいましたら教えてください。 下記 3 2023/04/25 11:22
- その他(コンピューター・テクノロジー) 正規表現の置換で一部の文字列をそのまま残したい 2 2022/05/03 19:19
- その他(プログラミング・Web制作) テキストエディタで複数行にわたる文字列の行頭に番号を振る方法 4 2023/03/11 12:57
- フリーソフト サクラエディタの正規表現(grep機能)の使い方 3 2022/06/22 10:29
- Ruby power BI クエリエディター 〇〇を含む文字列置換 1 2022/10/16 17:34
- Word(ワード) ワードフォント 一括置換の方法 4 2022/12/31 00:27
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
vba クリップボードクリアにつ...
-
pip --versionがエラーになる
-
数学、プログラミング、物理、...
-
Python 3.12.2 か一番最新のパ...
-
pythonの実行に関する質問
-
CSVファイルの複数行削除
-
ネットワークフォルダの中身を...
-
OS入ってる機器のソフト・アプ...
-
パイソンのソースコードをChatG...
-
Python... 環境設定 初心者です...
-
オブジェクト指向プログラミン...
-
IT業で開発をされてる方々に質...
-
画像生成AIのプロンプトの作り...
-
Pythonのエラーメッセージをコ...
-
プログラミング ソースコード
-
ExcelVBAでFormulaR1C1を列範囲...
-
HTMLソースが表示のページのも...
-
PowerAutomateで運賃検索がした...
-
google Colabでmatplotlibの描...
-
VBSでテキストファイルの2行目...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
vba クリップボードクリアにつ...
-
CSVファイルの複数行削除
-
OS入ってる機器のソフト・アプ...
-
Python 3.12.2 か一番最新のパ...
-
pythonの実行に関する質問
-
パイソンのソースコードをChatG...
-
画像生成AIのプロンプトの作り...
-
数学、プログラミング、物理、...
-
pip --versionがエラーになる
-
Google ColaboでGUI作成
-
Python... 環境設定 初心者です...
-
HTMLソースが表示のページのも...
-
ネットワークフォルダの中身を...
-
MOVEコマンドでサブフォルダー...
-
google Colabでmatplotlibの描...
-
VBAでパワーシェルを実行したい...
-
Pythonでの文字列からfloatへの...
-
Webサイト内に埋め込んだmp4動...
-
初心者powershellのPS1ファイル...
-
pythonについて(初心者です)
おすすめ情報
やりたいことをまとめてみました。
「wordtest1.txt」内の文字列から「/test/(apple.*?)/」を「\n\1\n」に置換して「wordtest2.txt」の名前で保存。
次に「wordtest2.txt」内から「^apple.*$」となっている文字列を抽出して、「wordtest3.txt」として保存。
grep -o ^apple.*$ wordtest2.txt > wordtest3.txt
最後に、「wordtest3.txt」の抽出された文字列から重複文字列(重複行)を削除して、「wordtest4.txt」として保存。
awk '!a[$0]++' wordtest3.txt > wordtest4.txt
文字列置換と文字列抽出、重複文字列削除(重複行削除)を連続して行えたら良いと思っております。
perl -npe 's|/test/(apple.*?)/|\n$1\n|;' wordtest1.txt > wordtest2.txt ; grep -o ^apple.*$ wordtest2.txt > wordtest3.txt ; awk '!a[$0]++' wordtest3.txt > wordtest4.txt
上記で上手く出来たと思ったのですが、再度実行してみたら上手く行かなくなってしまいました。
どこかでミスをしているのかなぁ。。。
何度も申し訳ありません。
wordtest.shに
perl -npe 's|/test/(apple.*?)/|\n$1\n|;' wordtest1.txt > wordtest2.txt
と記載して「sh -x wordtest.sh」と実行してみました。
実行内容は
+ perl -npe 's|/test/(apple.*?)/|?n$1?n|;' wordtest1.txt
と表示。
出力されたwordtest2.txtの内容はwordtest1.txtと変わらずでした。
逆スラッシュが「?」に変わってしまっているのが気になります。
考えられる原因は分かりますでしょうか。