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

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

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

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

sh

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

zsh

zshは、UNIX系OSのシェルの1つです。 cshやksn系のコマンドライン編集機能も実装されたシェルです。

Q&A

解決済

2回答

1226閲覧

[sh] あるファイルに行ったマッチングの結果を使って、別なファイルを加工したい

SAKASHITA-Koki

総合スコア27

bash

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

sh

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

zsh

zshは、UNIX系OSのシェルの1つです。 cshやksn系のコマンドライン編集機能も実装されたシェルです。

0グッド

0クリップ

投稿2020/07/25 16:47

やりたいこと

markdown

1<!-- a.md --> 2 3- a: aの説明 4 - b: bの説明 5 - c: cの説明

markdown

1<!-- b.md --> 2 3- a 4 - c 5 - d

みたいなMarkdownが2つあったとします。

a.mdにはそれぞれのアイテムの説明がついています。
b.mdには説明はなく、bが削除され、dが追加されています。

これらから、

markdown

1<!-- output --> 2 3- a: aの説明 4 - c: cの説明 5 - d

というMarkdownを作りたいと思っています。
つまり、b.mdの階層構造をベースに、共通するアイテムの説明をa.mdから引っ張って来たいです。
bがb.mdにないからと言って追加したりせず、dの説明がa.mdにないからといって削除したりしない。
(これをマージというのかは微妙ですが・・・)

試したこと

とりあえずgrep -o -f b.md a.md | sed -E 's/^/(/;s/$/)(.*)/'で、

(- a)(.*) ( - c)(.*)

と、a.mdとb.mdの共通するアイテムを見つけ、そこから説明をキャプチャできそうなパターンを作ることはできます。このパターンでa.mdにマッチングをかければ1番目のグループに対象の階層構造2番目のグループに説明をキャプチャできるはず。その結果を使ってb.mdの末尾を2番目のグループで置換できれば望みのデータが得られそうなんですが・・・

**「a.mdにマッチングをかける」「その結果を使ってb.mdを置換する」**を上手く接続できません。for等を使って1つ1つ変数に入れてやれば自分でもできそうな気はしますが、いまいちshellっぽくない感じがします。

xargsとか使うのかなと思うのですが・・・
shellっぽくいい感じにできませんか・・・?

環境としてはMacOS Catalinaのzshですが、あまり特殊なコマンドは使わないで汎用的なものにしていただけると嬉しいです。

よろしくお願いします。

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

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

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

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

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

guest

回答2

0

ベストアンサー

このパターンでa.mdにマッチングをかければ

は、

zsh

1grep -E -f <(grep -o -f b.md a.md | sed -E 's/^/(/;s/$/)(.*)/') a. 2md 3または、 4grep -o -f b.md a.md | sed -E 's/^/(/;s/$/)(.*)/' | xargs -I{} grep -E {} a.md

で出来ますが、その先をどうしたいのかよく分かりません。

そもそものやりたいことは、下記で出来ると思います。

zsh

1sed -f <(sed 's/^/s#/;s/:/#\&/;s/$/#/' a.md) b.md

投稿2020/07/25 19:12

otn

総合スコア85901

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

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

SAKASHITA-Koki

2020/07/26 00:59

なるほど・・・とても鮮やかです。 - sedのsコマンドの区切り文字は`/`でなくてもいい(sの次の文字が区切り文字となる) - sedのsコマンドにおける`&`は置換前の文字列を意味する - Process Substitution`<(...)`機能 - sedコマンドをsedを使って作るというアイデア 勉強になりました・・・ありがとうございます!
otn

2020/07/26 01:21

解説がいるかなと思ったのですが、解説無しで自分で調べて理解できたと言うことは、シェルについて次に質問する場合は初心者マークを取って良いのでは?と思います。
SAKASHITA-Koki

2020/07/26 02:16

そう言っていただけると恐縮です・・・!! 次からはそうさせていただきます。
guest

0

これは完全に私の挙げた例が不適切で、言葉足らずだったのですが、a.mdの階層構造と説明は、必ずしも:で区切られているのではなく、-や単に など、予測のできないものでした。一方でb.mdには絶対に説明が付かず、純粋に階層構造のみを表します。
本当にすみません・・・

otnさんに頂いた回答sed -f <(sed 's/^/s#/;s/:/#\&/;s/$/#/' a.md) b.mdは質問文からすれば完璧でした。ありがとうございます!
また、otnさんの回答から、以下のことを学びました。

  • sedのsコマンドの区切り文字は/でなくてもいい(sの次の文字が区切り文字となる)
  • sedのsコマンドにおける**&は置換前の文字列を意味する**
  • Process Substitution<(...)機能
  • sedコマンドをsedを使って作るというアイデア

そこで、otnさんの回答をベースにして、当初自分が考えていたような、:以外の多くの区切り文字に対応できるワンライナーを考えました。

sed -f <(sed -f <(sed 's/^/s@/;s/$/@s#\&#\\&@/' b.md) a.md | sed -E '/^[^(s#)]/d;s/$/#/') b.md

sedコマンドを作るためのsedコマンドを作るためのsedコマンドです・・・。
処理の流れを説明しようとしましたが、上手く文章化できませんでした・・・すみません。
figure
1つずつパズルのようにコマンドを組み上げていくのは楽しかったです。
ありがとうございました・・・!!

投稿2020/07/26 02:13

SAKASHITA-Koki

総合スコア27

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

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

otn

2020/07/26 02:44

「aの説明」の文字列中に # や @ という文字が出てくるかも知れない とか、考えるともっと複雑ですね。 頭が痛い。sedでも不可能では無いと思いますが、他の言語を使うかな。 おそらくYAML形式のファイルではないかと思うので、もしそうならYAMLライブラリのある言語を使うと、コードは長くはなりますが、頭が痛くならずに書けると思います。
SAKASHITA-Koki

2020/07/26 03:41

そうですね・・・これ以上は考えたくないです・・・ ご丁寧にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問