web-dev-qa-db-ja.com

bashコマンドライン-sh -cで複数行を単一行に変換する方法

OSXコマンドラインでは、次のようなロジックがあります。

for i in {1..10}
do
   for j in {1..10}
   do
       echo "test inner"
   done;
   echo "test outer"
done

それはうまくいきます。しかし、私はNohupから実行したいと思っています。したがって、Nohup sh -c "{a single line}"に収まるように、上記を1行に結合する必要があります

ただし、次の行はエラーになります。上からすべての改行をスキップしただけです。

sh -c 'for i in {1..10} do for j in {1..10} do echo "test inner" done; echo "test outer" done'

エラー:

sh: -c: line 0: syntax error near unexpected token `echo'
sh: -c: line 0: `for i in {1..10} do for j in {1..10} do echo "test inner" done; echo "test outer" done'

編集:

コマンドの資格情報がわずかに保護されているため、ファイルとして実行したくありませんでした。私が考えることができる最も簡単な方法は、それをコマンドとして実行して、共有VMにファイルを残さないようにすることです。これがどのように資格情報を保護するのか、またはもっと良い方法があるのか​​わかりません。より多くの提案/アイデアは大歓迎です。

編集:

Bashと一重引用符を使用すると機能します。 (ティガーの答えに基づく)

bash -c 'for i in {1..10}; do for j in {1..10}; do echo "test inner"; done; echo "test outer"; done;'

2
Weishi Zeng

私の見たところ、2つの選択肢があります。

  1. それをスクリプトファイルに入れて実行します
  2. 上記の大きなコードウィンドウのすべての改行をセミコロンで置き換えます

個人的には1で行きます。

3
tink

sh -cの引数に改行文字があっても問題ありません。 {1..10}zsh構文ですが(現在、他のいくつかのシェルでサポートされています)、shではありません。 sh{1..20}に対してecho {1..20}以外を出力する場合、それはPOSIX準拠違反であり、新しいバージョンで修正する準備ができているはずです。以下を使用できます。

zsh -c '
  for i in {1..10}
  do
     for j in {1..10}
     do
         echo "test inner"
     done
     echo "test outer"
  done'

または

sh -c '
   i=1; while [ "$i" -le 10 ]
   do
     j=1; while [ "$j" -le 10 ]
     do
       echo "test inner"
       j=$((j + 1))
     done
     echo "test outer"
     i=$((i + 1))
  done'

しかし、そのために100個のechoコマンドを実行するのは愚かな感じですが、1つのコマンドだけで実行できます。

awk 'BEGIN{
  for (i=1; i<=10; i++) {
    for (j=1; j<=10; j++)
      print "test inner"
    print "test outer"
  }}'

あなたが望むなら、あなたは単一の行に置くことができます:

awk 'BEGIN{for(i=1;i<=10;i++){for(j=1;j<=10;j++)print"test inner";print"test outer"}}'
3

これを1行に変換します。正しい場所にいくつかの;を追加しました:

for i in {1..10}; do for j in {1..10}; do echo "test inner ${j}"; done; echo "test outer ${i}"; done;

上記の行はbashで機能しますが、これをsh -cで実行するには、shがサポートしていないため、{1..10}を拡張する必要があります(私の知る限り)。範囲構文。その場合、次の行が機能します。

sh -c 'for i in 1 2 3 4 5 6 7 8 9 10; do for j in 1 2 3 4 5 6 7 8 9 10; do echo "test inner ${j}"; done; echo "test outer ${i}"; done;'

注:確認のために${j}${i}を追加しました。

2
Tigger