%E3%81%A7%E4%BD%BF%E7%94%A8%E3%81%95%E3%82%8C%E3%80%81%E5%A4%89%E6%95%B0%E3%81%AB%E4%BF%9D%E5%AD%98%E3%81%95%E3%82%8C%E3%81%9F%E5%A0%B4%E5%90%88%E3%81%AF%E5%8A%B9%E6%9E%9C%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82.png)
CLI で実行する場合:
curl time.com | sed -n 's/.*href="\([^"]*\).*/\1/p' | tr " " "\n"
すると、予想どおり、ページから へのサニタイズされたリンクのリストがSTDOUT
、それぞれ新しい行に表示されていきます。
ただし、それを変数に保存し、echo
それをから実行しようとすると、次のようになりますscript.sh
。
PAGE_LINKS=$(curl time.com | sed -n 's/.*href="\([^"]*\).*/\1/p' | tr " " "\n")
echo $PAGE_LINKS
すべてのリンクをスペースで区切って 1 行に表示します。tr
無視されたかのようになります。
私は次のようなことをいろいろ試しました
HREFS=$(tr " " "\n" < "{PAGE_LINKS}")
echo $HREFS
しかし、その後file too long
エラーが発生します。何か提案はありますか?
答え1
bash
構造のマニュアルページによると$(command)
:
Bash は、コマンドを実行し、コマンド置換をコマンドの標準出力に置き換えて展開を実行します。末尾の改行は削除されます。埋め込まれた改行は削除されませんが、単語分割中に削除される可能性があります。
tr
これは問題ではありませんが、末尾bash
に改行がある場合はそれを削除し、単語分割中に他の改行を削除します。これはドキュメントに記載されている動作です。
ほとんどの場所でこの動作が望ましいと思います。ファイル名のリストを含むファイルがある場合は、次のようになります。
for FILENAME in $(cat somefile)
do
...
done
somefile
ファイル名のリストを反復します。改行によってファイル名として使用する単語のリストが台無しになったり、for-do-done ループが台無しになったりするのは望ましくありません。
答え2
問題は ではなくtr
、変数展開をどのように出力しているかにあります。
echo $PAGE_LINKS
変数の展開を引用します:
echo "$PAGE_LINKS"
それ以外の場合、拡張は の値 (デフォルトではスペース、タブ、改行) に従って単語分割されIFS
、パス名拡張 ( *
、?
、[]
) が実行されます。
あなたの場合、単語の分割が行われ、改行で区切られた各要素が個別に取得され、最終的にスペースで区切られたエンティティとして表示されます。引用符を使用すると、単語の分割 (およびパス名の展開) が防止されるため、展開全体が単一のエンティティとして取得されます。