このシェルスクリプトをファイルに保存しました。このスクリプトはいくつかの基本的な文字列置換を実行します。
#!/bin/sh
html_file=$1
echo "html_file = $html_file"
substr=.pdf
pdf_file="${html_file/.html/.pdf}"
echo "pdf_file = $pdf_file"
これをコマンドラインに貼り付けると正常に動作します。
$ html_file="/home/max/for_pauld/test_no_base64.html"
echo "html_file = $html_file"
substr=.pdf
pdf_file="${html_file/.html/.pdf}"
echo "pdf_file = $pdf_file"
与えられた
html_file = /home/max/for_pauld/test_no_base64.html
pdf_file = /home/max/for_pauld/test_no_base64.pdf
上記のecho出力は次のとおりです。期待どおりに動作します。
しかし、スクリプトを呼び出すと
$ saucer "/home/max/for_pauld/test_no_base64.html"
私は次のような結果を得ます。
html_file = /home/max/for_pauld/test_no_base64.html
/home/max/bin/saucer: 5: /home/max/bin/saucer: Bad substitution
私のスクリプトは異なるバージョンのbashや他のものを使用していますか? Shebangラインを変更する必要がありますか?
答え1
shとは何ですか?
sh
(またはShell Command Language)は、次のように開発されたプログラミング言語です。POSIX規格。多くの実装があります(ksh88
、、、dash
...)。bash
実装と見なすこともできますsh
(下記参照)。
sh
これは実装ではなく仕様なので、/bin/sh
ほとんどのPOSIXシステムではシンボリックリンク(またはハードリンク)の実際の実装です。
バッシュとは?
bash
もともとは互換性の実装のために意図されていましたが、sh
(POSIX標準よりも数年前にありますが)、時間の経過とともに多くの拡張が行われていました。これらの拡張の多くは、有効なPOSIXシェルスクリプトの動作を変更できるため、bash
それ自体は有効なPOSIXシェルではありません。代わりにPOSIXシェル言語の方言です。
bash
スイッチのサポートにより、--posix
POSIXとさらに互換性があります。 sh
.
sh=バッシュ?
長い間、ほとんどのGNU / Linuxシステムを/bin/sh
指すために使用されてきました。/bin/bash
その結果、両者の違いを無視することはほぼ安全です。しかし、最近になって変化が始まりました。
システムのいくつかの一般的な例/bin/sh
(/bin/bash
一部は/bin/bash
存在しない場合があります)は次のとおりです。
sh
最新のDebianとUbuntuシステムはへのデフォルトのシンボリックリンクですdash
。- 忙しい箱、通常はLinuxシステムの起動時間の一部として実行されます
initramfs
。ash
シェルを使用して実装されます。 - BSDと通常Linux以外のシステム。 OpenBSD は
pdksh
Korn シェルの子孫を使用します。 FreeBSDはsh
もともとUNIX Bourneシェルの子孫です。 Solarisには独自のシステムがありますが、sh
長い間POSIXと互換性がありませんでした。ガボプロジェクト。
/bin/sh
私のシステムにどのような問題があるのか、どうすればわかりますか?
問題は、これが/bin/sh
シンボリックリンクでもハードリンクでもよいということです。シンボリックリンクの場合、持ち運べる解決策は次のとおりです。
% file -h /bin/sh
/bin/sh: symbolic link to bash
ハードリンクなら試してみてください
% find -L /bin -samefile /bin/sh
/bin/sh
/bin/bash
実際、この-L
フラグにはハードリンクだけでなくシンボリックリンクも含まれますが、このアプローチの欠点は移植性がないことです。 - POSIX不要 find
この-samefile
オプションはサポートされていますが、両方GNUを探すそしてFreeBSDを探すそれをサポートしてください。
シェルボーンライン
最終的に「shebang」行を作成し、どちらを使用するかを決定します。
例えば
#!/bin/sh
sh
(そしてそれが指すものは何でも)使用します。
#!/bin/bash
/bin/bash
利用可能な場合に使用します。それ以外の場合は、エラーメッセージで失敗します。もちろん、次のような他の実装を指定することもできます。
#!/bin/dash
どちらを使うのか
私のスクリプトでは、sh
次の理由でを好みます。
- それは標準化されています
- より簡単で習得が簡単です。
bash
POSIXシステム間で移植可能です。そうでない場合でもsh
bash
使用すると利点もあります。その機能は、プログラミングをより便利にし、他の現代のプログラミング言語でプログラミングするのと似ています。これには、スコープ付きのローカル変数や配列などが含まれます。 Plainsh
は非常にミニマルなプログラミング言語です。
答え2
@Hunter.S.Thompsonの優れた答えに加えて、スクリプトの移植不可能な部分は次のとおりです。
pdf_file="${html_file/.html/.pdf}"
これは${variable/search/replace}
GNU拡張です。ただし、純粋なPOSIXを使用すると、これを簡単に回避できます。
pdf_file="${html_file%.html}".pdf
ハンターに続いて、これはシェバンを次に変更するよりも優れた解決策です。#! /bin/bash