字符串连接在bash中不起作用

时间:2019-01-15 03:48:15

标签: bash

我正在编写一个shell脚本,该脚本读取文本文件并基于它们创建JSON键值对。 key是文件名,而value是文件的随机行。

麻烦是当我在全局变量key中将valuedata串联时。

当我运行下面的代码时:

data='{'

for file in $(ls _params)
do
    key=${file%.txt}

    f_line=$(($$%100))
    value=$(sed "${f_line}q;d" "./_params/$file")

    # assembles key-value pairs
    data=$data\"$key\":\""value"\",
done

data=${data%?} # removes last comma
data="$data}"

echo $data

我的输出是:{"firstName":"value","lastName":"value"}

但是将字符串"value"更改为变量$value,如下所示:

data='{'

for file in $(ls _params)
do
    key=${file%.txt}

    f_line=$(($$%100))
    value=$(sed "${f_line}q;d" "./_params/$file")

    # assembles key-value pairs
    data=$data\"$key\":\"$value\",
done

data=${data%?} # removes last comma
data="$data}"

echo $data

输出混乱:"}"lastName":"Adailee

我希望在$data变量中存储以下内容:{"firstName":"Bettye","lastName":"Allison"}

注意:我的bash版本是4.3.48。

注意:在我的档案_params中,我有两个文件firstName.txtlastName.txt,每行都有随机名称。

2 个答案:

答案 0 :(得分:2)

$value显然以回车符(\r,U + 000D)结尾。结果,当您打印它时,光标移回到该行的开头,随后的字符从第一列开始打印,覆盖之前的内容。 (当然,这并不影响字符的实际顺序;在打印时,它只会令人困惑地显示。)

要解决此问题,您可以编写

value="${value%$'\r'}"

删除尾随回车。

答案 1 :(得分:2)

正如@ruakh所建议的,具体问题是您的输入文件。以下是重现您的问题并进行验证的步骤:

我创建了两个firstNames.txt文件,其中A B C D重复了100次:

$ cat ABCD
A
B
C
D
$ for _ in $(seq 1 100); do cat ABCD >> _params/firstName.txt

,然后与W X Y Z类似,用于lastNames.txt。然后我运行了您的脚本:

$ bash q.sh 
{"firstName":"A","lastName":"W"

但是,如果我使用unix2dos(来自dos2unix软件包)将其转换为\ r \ n行尾。

$ unix2dos _params/firstName.txt 
unix2dos: converting file _params/firstName.txt to DOS format...
$ unix2dos _params/lastName.txt 
unix2dos: converting file _params/lastName.txt to DOS format...
$ bash q.sh 
"}"lastName":"W

因此,您可能可以使用dos2unix来修复输入文件(或打开vim并先执行:set ft=unix然后执行:x)。

但是我想让您了解其他三件事。

  1. $$不是随机数,它是您当前进程的PID。
  2. 最佳做法不是解析ls,而是改用1
  3. 您可以解决围栏问题,而无需删除刚放置的逗号,方法是从空的分隔符开始,并将其设置为循环的第一次迭代后的逗号。

这是我对改进脚本的建议(一旦您在输入中修复了换行符):

#!/bin/bash
data='{'
sep=""

for file in _params/*
do
  key=${file%.txt}
  file_length=$(wc -l < ${file})
  f_line=$(( (RANDOM % file_length) + 1 ))
  value=$(sed "${f_line}q;d" "${file}")

  # assembles key-value pairs
  data="${data}${sep} \"$key\":\"$value\""
  sep=","
done

data="${data} }"

echo $data