いくつかのことを自動化するためのスクリプトに取り組んでいます。 sedコマンドを実行してcurlの出力をファイルの行番号に挿入する際に問題が発生しました
コマンドの複数のバリエーションを試しましたが、sedからエラーが発生するだけです。
sed "49i/.*/\"$(curl URL)\"/" file.php
sed: -e expression #1, char 105: extra characters after command
どんなアイデアもありがとう
_curl URL
_の出力($()
がtrailingnewline(s)を削除した後)には、おそらく改行文字が含まれています。これは、sed
のスクリプトであると想定されるコマンドライン引数に挿入されます。ツールはコードを解析し、_49i
_の後に改行を検出し、スクリプト内の次のコマンドとして続くものを解釈します。
エラーが発生しました。さらに悪いことに、curl
からの出力が構文的に有効なsed
コードをスクリプトに挿入する可能性があります。あなたはこれを望まない。
$(curl URL | tr -d '\n')
を使用してall改行を削除しても、curl
の出力はそのまま挿入されない場合があります(たとえば、円記号には特別な意味があります)。
解決策:curl
に一時ファイルに書き込んでから、sed
にファイルを出力させます。ファイルの内容はコードとして解釈されません。
curl
からの出力を、49行目の元のコンテンツの前に表示したいようです。その場合は、48行目でr
を使用する必要があります(r
は後で出力するためにテキストをスケジュールするため)。
コードは_/.*/"curl output here"/
_の形式で何かを挿入しようとします。これがs
の構文をi
で使用しようとしたことによるアーティファクトではない場合は、これらの追加のフラグメントもファイルに書き込む必要があります。
通常、_curl -o
_を使用して、curl
をファイルに書き込むことができます。この場合、末尾の改行が削除されないため、希望どおりにならない可能性があります(使用した$()
は削除します)。だからたぶんこれ:
_tmpfile="$(mktemp)"
printf '/.*/"%s"/' "$(curl URL)" >"$tmpfile"
sed "48 r $tmpfile" file.php
rm "$tmpfile"
_
一般に、curl
からの出力が長すぎると失敗することに注意してください。より堅牢な解決策は、curl
をファイルに直接出力し、次のステップで 改行を末尾から削除する にすることです。
一時ファイルへのパスに改行を含めることはできません。改行が含まれている場合、パスの一部がsedコマンドとして解釈され、無効である可能性があります。あなたが経験したものと幾分似ているバグ。 _$TMPDIR
_に改行が含まれていない限り、パスに改行は含まれません(ただし、実際には改行を含めるべきではありません)。問題が発生した場合(たとえば、mktemp
が利用できない場合)、一時的な場所を選択する別の方法を使用します。最も基本的な設定では、場所がハードコーディングされている場合があります(ただし、スクリプトの複数のインスタンスを同時に実行しないでください)。
sed
のi...\n
コマンドの構文はs/.../.../...
と同じではありません。これが、ここでの主な問題だと思います。 curl
出力に改行が含まれている可能性があり、最終的にi
コマンドが終了するという事実に加えて。
s/find/replace/
はfind
を検索し、それをreplace
と交換します
以下の例では、正規表現3
に一致するテキストがスワップアウトされています。
$ echo -e "1\n2\n3\n4\n5" | sed 's/3/new line/'
1
2
new line
4
5
inew line
は、一致した行の前にnew line
を挿入します
以下の例では、アドレスまたは一致を指定していないため、every入力行の前にnew line
が挿入されています。
$ echo -e "1\n2\n3\n4\n5" | sed 'inew line'
new line
1
new line
2
new line
3
new line
4
new line
5
あなたがしようとしていることは、与えられた行番号(別名 "address")に新しい行を挿入することであるように見えます。これはこのように達成することができます。 i
コマンドは改行(または文字列の終わり)で終了することに注意してください-new line
は前に挿入され、3行目を置き換えません。
$ echo -e "1\n2\n3\n4\n5" | sed '3inew line'
1
2
new line
3
4
5
curl
の出力を使用していると、これに改行が含まれていることに気付くかもしれません。これにより、i
コマンドが終了します...したがって、変換する必要があります。 curl
の出力を1行にするか、最初の行のみを含めます。head
やxxd
などのツールを使用して次のことができます。
$ curl "${url}"
line one
line two
line three
最初の行のみを保持します。
$ new_line="$(curl -s "${url}" | head -n 1)"
$ echo -e "1\n2\n3\n4\n5" | sed '3i'"${new_line}"
1
2
line one
3
4
5
すべての改行(\r\n
および\n
)をリテラル文字\n
にエスケープします。 sed
は、これらを改行に変換し直します。
$ new_line="$(curl -s "${url}" | xxd -p | sed -re 's/(0d)?0a/5c6e/g;s/5c6e$//' | xxd -r -p)"
$ echo -e "1\n2\n3\n4\n5" | sed '3i'"${new_line}"
1
2
line one
line two
line three
3
4
5
すべての改行(\r\n
および\n
)をリテラル文字\\n
にエスケープします。次に、sed
はこれらをリテラル文字\n
に変換し、1行が挿入されます。
$ new_line="$(curl -s "${url}" | xxd -p | sed -re 's/(0d)?0a/5c5c6e/g;s/5c5c6e$//' | xxd -r -p)"
$ echo -e "1\n2\n3\n4\n5" | sed '3i'"${new_line}"
1
2
line one\nline two\nline three
3
4
5
これは、それが可能であることを示していますが、より良いアプローチは、このようにhead
、curl
、およびtail
を使用してファイルを再構築することです。 ..将来的にはもっと読みやすくなるでしょう:
$ echo -e "1\n2\n3\n4\n5" > "${file}"
$ tmpfile="$(mktemp)"
$ ( head -n 2 < "${file}"; curl "${url}"; tail -n +3 < "${file}" ) > "${tmpfile}"
$ mv "${tmpfile}" "${file}"
$ cat "${file}"
1
2
line one
line two
line three
3
4
5