Bashスクリプトの変数に代入

Bashスクリプトの変数に代入

次のスクリプトがあり、空のテキストファイルを作成しようとしています。試してtouchもう一度試しましたがecho -n >失敗しました。

#!/bin/bash

set filename_result="contents"

echo "filename=$filename_result" # Shows: filename=

rm -f "$filename_result".json

touch $filename_result # Error: usage: touch [-A [-][[hh]mm]SS] [-acfhm] [-r file] [-t [[CC]YY]MMDDhhmm[.SS]] file ...
# Note that `% touch myfile` works fine on the command line

touch -- "$filename_result" # Error: touch: : No such file or directory

echo -n > "$filename_result" # Error: No such file or directory

echo "[" >> "$filename_result"

for file in *json
do
    echo "examining file: $file"
    echo "\n" >> "$filename_result"
    cat $file >> "$filename_result"
    echo "\n" >> "$filename_result"
done

echo "\n]" >> "$filename_result"

mv $filename_result "$filename_result".json

編集:画面filename_result変数に印刷すると、設定後に空白が表示されますか?

echo "filename=$filename_result" # Shows: filename=

答え1

set filename_result="contents"割り当てられた値がありませんfilename_result。最初の位置パラメータに割り当てられ、値自体はですfilename_result=contents。例:

$ set filename_result="contents"
$ echo "$1"
filename_result=contents

変数はfilename_result存在せず、$filename_result空の状態に展開されます。"$filename_result"これはと同じです""

set filename_result="contents"ほしいものよりも

filename_result="contents"

答え2

この試み:

filename_result=contents
touch -- "$filename_result"

または:

set contents
touch -- "$1"

答え3

複数のJSONファイルの内容を要素として含むJSON配列を作成したいようです。各ファイルの内容の間にカンマ挿入を省略したことを確認しました。これは間違ったJSONを引き起こします。

代わりに、スクリプトを次のコマンドで置き換えることができます。

jq -s . ./*.json >outfile

その後、現在のディレクトリから名前が一致するすべてのファイルを読み取り、*.json各ファイルのJSONドキュメントを1つの要素として使用して配列を作成します。出力が記録されますoutfile

jqほとんどのUnicesで動作するコマンドラインJSONパーサーです(パッケージマネージャを確認してください)。-s(または)オプションは、--slurp先ほど説明したものと正確に一致します(配列で読み取る)。

これは.「IDフィルタ」で、その役割はデータのみを渡すことです。


あなたのコードに関して:

変数を設定しようとする以外はset(これはKamil Machorovskyは次のように指摘した。cshすでにこれがシェルで行われる方法ですtcsh。いくつかのコマンド(特にループ内部コマンド)を一緒にグループ化することで、出力を簡素化できます。touch存在しないファイルにリダイレクトするとファイルが生成されるため、必要ありません。

以下は、問題に関する私自身の見解です。各ファイルの内容の間に欠落しているコンマも挿入されます。

#!/bin/sh

outfile=outfile

# Will truncate (empty) the file if it exists,
# or create it if it doesn't.
echo '[' >"$outfile"

# Get a list of all JSON files into the list
# of positional parameters.
set -- ./*.json

# Loop over all but the last file.
# Output each file and a comma.
while [ "$#" -gt 1 ]; do
    # The "current" file that we're working on is "$1",
    # the first one in the list.

    cat "$1"
    echo ,

    shift  # shifts this file off the list
done >>"$outfile

# The last file should not have comma after it.
{
    cat "$1"
    echo ']'
} >>"$outfile"

このwhileループは、位置引数のリスト(リストはを使用して生成されますset)のJSONファイルを繰り返します。各ファイルの後にコンマを付けて出力したいのですが、最後のファイルの後にコンマを付けてはいけません。したがって、ループは、リストの最後のファイル(位置$#引数リストの長さ)を除くすべてのファイルが削除されるまで繰り返されます。

{ ...; }最後のファイルは最後のファイルによって処理されます。中括弧内にコマンドセットをグループ化すると、単一のリダイレクトを介してこれらすべてのコマンドの出力を一度にリダイレクトできます。同様に、ループの出力は単一のリダイレクトを介してリダイレクトできます。


同じ方法ですが、GNUを使用してくださいawk

awk 'BEGIN   { print "[" }
             { print }
     ENDFILE { if (FILENAME != ARGV[ARGC-1]) print "," }
     END     { print "]" }' *.json

GNUには、標準とブロック(ここでは出力配列の最初と最後の区切り文字として使用されます)に加えて、awkブロックがあります。これは(驚くべきことに)各個々の入力ファイルが処理される前後にトリガされます。ここでは、出力の各ファイルの内容の間にカンマを使用します(最後のファイルの後は除く)。BEGINEND[]BEGINFILEENDFILEENDFILE

この{ print }ブロックは、変更なしで各ファイルのすべての行を渡します。

FILENAMEARGVおよびは、GNUが自動的に現在のファイル名、スクリプトに提供されている引数のリスト(この場合はファイル名)、およびファイル名の数で自動的に入力する変数ですARGCawk

関連情報