URLのリストをタイトル付きのMarkdownリンクリストにワンライナーで変換する
こんにちは。サービス開発室の武田です。
本文は後に回して、先に結論を置いておきます。url_list.txt
を用意し、このコマンドを一発たたけばOKです!macOSで動作確認はしましたが、移植性についてはそこまで考慮していませんので悪しからず。
cat url_list.txt | grep -E '^https?://' | xargs -n1 curl -s -w '\nURL: %{url}\n' | grep -oE '<title>.*</title>|^URL: .*' | awk 'NR%2==1{gsub(/<\/?title>/, ""); title=$0} NR%2==0{gsub(/URL: /, ""); printf("- [%s](%s)\n", title, $0)}'
ここから本文
ブログなどを書いていて、URLをリンクにしたいというニーズはよくあります。たとえばDevelopersIOでは、記事内にURLを置いておくと、自動的にカード型のリンクに置換してくれます。
https://www.example.com
この機能はとても便利で多用するのですが、1記事内にURLが多いと裏側での変換処理が追いつかず、場合によってはタイムアウトにもなってしまうというのは注意すべき点です。そのため自前でMarkdownのリンク表記をしておけば、変換処理も不要ですし、見た目も悪くありません。
[Example Domain](https://www.example.com)
さてMarkdown表記ですが、1個2個のURLであれば手動でやってもさほど苦ではありません。しかしこれが20個30個となってくるとどうでしょう?さすがに嫌になります。最初はAIさんにやってもらうことも考えたのですが、標準機能ではスクレイピングできません。というわけでコマンドを使ってバチっと解決しましょう。
やってみた
というわけで、最初にも掲載しましたが、次のようなワンライナーを実行することでバチっと解決できます。
cat url_list.txt | grep -E '^https?://' | xargs -n1 curl -s -w '\nURL: %{url}\n' | grep -oE '<title>.*</title>|^URL: .*' | awk 'NR%2==1{gsub(/<\/?title>/, ""); title=$0} NR%2==0{gsub(/URL: /, ""); printf("- [%s](%s)\n", title, $0)}'
例として、次のようなリストを用意します。
https://dev.classmethod.jp/articles/aws-security-service-volume-discount/
https://dev.classmethod.jp/articles/python-define-functions-arguments/
https://dev.classmethod.jp/articles/aws-summary-2025/
https://dev.classmethod.jp/articles/contentful-avoid-long-text-field-limits/
実行結果は次のようになります。
- [AWS Security Hubなどセキュリティサービスのボリュームディスカウントを確認してみた | DevelopersIO](https://dev.classmethod.jp/articles/aws-security-service-volume-discount/)
- [[Python] 関数定義時の特殊な引数宣言についてまとめ | DevelopersIO](https://dev.classmethod.jp/articles/python-define-functions-arguments/)
- [【2025年】AWS全サービスまとめ | DevelopersIO](https://dev.classmethod.jp/articles/aws-summary-2025/)
- [[Contentful] 本文のMarkdownテキスト5万字制限に抵触した場合に考慮すること | DevelopersIO](https://dev.classmethod.jp/articles/contentful-avoid-long-text-field-limits/)
ワンライナーの解説
ワンライナーをそのまま使うでもいいですし、ちょっと改変したいという場合のために何をしているのか書いておきます。
cat url_list.txt
url_list.txt
ファイルの内容を標準出力に出力
grep -E '^https?://'
- 入力行から
http://
またはhttps://
で始まる行のみを抽出 -E
は拡張正規表現を使用するオプションです- URL以外の行を除外しており、文章などが混じっていてもスキップします
- 入力行から
xargs -n1 curl -s -w '\nURL: %{url}\n'
- 実際にリクエストをしてURLのドキュメントを取得
-n1
: 1行ずつcurlコマンドにURLを渡します。curlは標準入力からURLを渡せないため必要ですcurl -s
: 各URLに対してHTTPリクエストを実行します(-sは進捗を表示しないオプション)-w '\nURL: %{url}\n'
: レスポンスの後にURLを出力。次のコマンドにレスポンスだけではなくURLも渡す必要があるため付与しています
grep -oE '<title>.*</title>|^URL: .*'
- 不要な情報を除外
-o
: マッチした部分のみを出力。titleタグの内容とURLの行のみを抽出します
awk 'NR%2==1{gsub(/<\/?title>/, ""); title=$0} NR%2==0{gsub(/URL: /, ""); printf("- [%s](%s)\n", title, $0)}'
- 奇数行:titleタグを除去してtitle変数に保存
- 偶数行:「URL: 」を除去してMarkdownリンク形式で出力
オシャレポイントはcurl -w
で結果にURLを付与しているところです。これをしないとURLを変数などに一度保存し、あとで参照するのような手順が発生します。
使用上の注意
今回sleepなどを入れていないため、連続してリクエストをすることになります。同一ドメインのURLをたくさん並べる場合、連続したアクセスは利用規約などに抵触する可能性があります。そういったケースでは適切な間隔を空けるようにしてください。
リダイレクトには対応してません。その場合はcurl -L
とオプションを追加してください。
まとめ
Markdown形式でURLリンクのリストを簡単に作る方法について考えてみました。必要な時にサクッとコマンドで実行できるのはいいですね。