分配给 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 文档作为一个元素。输出将被写入outfile

jq是一个命令行 JSON 解析器,适用于大多数 Unices(检查你的包管理器)。-s(或)选项--slurp的作用正是我刚刚描述的(读入数组)。

.是“身份过滤器”,其作用是仅传递数据。


关于您的代码:

除了用于set尝试设置变量(这已被卡米尔·马乔罗夫斯基指出csh已经,这就是在和shell中完成的方式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循环迭代位置参数列表中的 JSON 文件(该列表是使用 创建的set)。我们想要输出每个文件,后跟一个逗号,但要单独处理最后一个文件,因为它后面不应该有逗号(这会破坏 JSON 格式)。因此,循环会迭代,直到我们移出列表中除最后一个文件之外的所有文件($#是位置参数列表的长度)。

{ ...; }最后一个文件由最后的处理。将一组命令分组在大括号内允许我们通过一次重定向一次性重定向所有这些命令的输出。同样,循环的输出可以通过单个重定向进行重定向。


相同的方法,但使用 GNU awk

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

GNUawk除了标准的BEGINandEND块(此处用于输出数组的初始[和最终分隔符)之外,还有 a和块。这些(毫不奇怪)是在处理每个单独的输入文件之前和之后触发的。我们在此处使用输出每个文件内容之间的逗号(最后一个文件之后除外)。]BEGINFILEENDFILEENDFILE

{ print }块只是传递每个文件的每一行,而不进行修改。

FILENAMEARGV和是 GNU将分别自动填充当前文件名、给脚本的参数列表(在本例中为文件名)和文件名数量的ARGC变量。awk

相关内容