バッシュ:文字列から改行文字を削除します (行を読み取ります)
質問
次の問題に遭遇しました。次のことを行う Linux bash スクリプトを作成しています。
- ファイルから行を読み取る
- 剥がす
\n
読み取った行末の文字 - そこにあるコマンドを実行します
例:コマンド.txt
ls
ls -l
ls -ltra
ps as
bash ファイルの実行では最初の行を取得して実行する必要がありますが、 \n
存在する場合、シェルは「コマンドが見つかりません:」と出力するだけです。ls "スクリプトのその部分はこのように見えます
read line
if [ -n "$line" ]; then #if not empty line
#myline=`echo -n $line | tr -d '\n'`
#myline=`echo -e $line | sed ':start /^.*$/N;s/\n//g; t start'`
myline=`echo -n $line | tr -d "\n"`
$myline #execute it
cat $fname | tail -n+2 > $fname.txt
mv $fname.txt $fname
fi
SOを尋ねる前に私が試したことがあるとコメントしました。何か解決策はありますか?ここ数時間、この件で頭を悩ませています...
解決
いつも好きです perl -ne 'chomp and print'
、改行をトリミングします。素敵で覚えやすいです。
例えば ls -l | perl -ne 'chomp and print'
しかし
しかし、それはあなたの問題ではないと思います。ファイル内のコマンドをシェルスクリプトの「読み取り」にどのように渡すのかを理解しているかどうかはわかりませんが。
このような独自のテスト スクリプト (test.sh)
read line
if [ -n "$line" ]; then
$line
fi
このようなサンプル入力ファイル (test.cmds)
ls
ls -l
ls -ltra
このように実行すると ./test.sh < test.cmds
, 現在の作業ディレクトリで最初のコマンド 'ls' を実行するという予想通りの結果が表示されます。
おそらく、入力ファイルに印刷不可能な文字が含まれているのではないでしょうか?
私のものはこんな感じです
od -c test.cmds
0000000 l s \n l s - l \n l s - l t
0000020 r a \n
0000023
以下のコメントから、入力ファイルにキャリッジ リターン ( " " ) が含まれているのではないかと思われますが、これは改行とは異なります。入力ファイルはもともとDOS形式ですか?その場合、期待どおりの結果を得るには、2 バイトの DOS 行末「 」を 1 バイトの UNIX 行「 」に変換する必要があります。
これは、コメントアウトされた行の「 」を「 」に置き換えることで実行できるはずです。
他のヒント
誰かがすでにシェルコマンドを実行するプログラムを書いています。shファイル
本当にファイルの最初の行だけを実行したい場合は、次のようにします。 head -n 1 file |sh
キャリッジリターンに問題がある場合: tr -d '\r' <file |sh
これを試してみました:
read line
echo -n $line | od -x
入力「xxxx」の場合、次の結果が得られます。
0000000 7878 7878
ご覧のとおり、ありません \n
変数の内容の最後に。オプションを指定してスクリプトを実行することをお勧めします -x
(bash -x script
)。これにより、すべてのコマンドが実行されると出力されます。
[編集] あなたの問題は、Windows上でcommands.txtを編集したことです。現在、ファイルには行区切り文字として CRLF (0d0a) が含まれており、混乱を招きます。 read
(そして ls\r
は既知のコマンドではありません)。使用 dos2unix
または同様の方法で Unix ファイルに変換します。
Bash 組み込み関数のみを使用して、キャリッジ リターンを改行に置き換えることもできます。
line=$'a line\r'
line="${line//$'\r'/$'\n'}"
#line="${line/%$'\r'/$'\n'}" # replace only at line end
printf "%s" "$line" | ruby -0777 -n -e 'p $_.to_s'
evalコマンドが必要です
#!/bin/bash -x
while read cmd
do
if [ "$cmd" ]
then
eval "$cmd"
fi
done
として実行しました
./script.sh < file.txt
file.txt は次のとおりでした。
ls ls -l ls -ltra ps as
働いていないにもかかわらず ls
, 、ぜひご覧ください。 find
の -print0
オプション
次のスクリプトは (少なくとも私にとっては) 機能します。
#!/bin/bash
while read I ; do if [ "$I" ] ; then $I ; fi ; done ;