在同一行Bash中回显多个变量

问题描述 投票:8回答:2

我想在同一行上回显两个变量。我想将2015-03-04.01.Abhi_Ram.txt存储在变量FILENAME中,将10存储在变量COUNT中,并同时回显它们。

Sample.txt

2015-03-04.01.Abhi_Ram.txt 102015-03-04.02.Abhi_Ram.txt 70

下面是我想出的代码:

for line in `hadoop fs -cat sample.txt`
do

VAR="${line}"
FILENAME=`echo ${VAR}|awk '{print $1}'`
COUNT=`echo ${VAR}|awk '{print $2}'`
COUNT_DT=`date "+%Y-%m-%d %H:%M:%S"`
echo db"|"Abhi_Ram"|"record_count"|"${FILENAME}"||"${COUNT}"||"${COUNT_DT} >> output.txt
done

I want the output as:

db | Abhi_Ram | record_count | 2015-03-04.01.Abhi_Ram.txt || 10 ||时间戳db | Abhi_Ram | record_count | 2015-03-04.02.Abhi_Ram.txt || 70 || timestamp

I'm getting the output as:

db | Abhi_Ram | record_count | 2015-03-04.01.Abhi_Ram.txt ||||时间戳db | Abhi_Ram | record_count | 10 |||||时间戳db | Abhi_Ram | record_count | 2015-03-04.02.Abhi_Ram.txt ||||时间戳db | Abhi_Ram | record_count | 70 ||||时间戳

有人可以指出我所缺少的东西吗?

bash echo
2个回答
12
投票

考虑:

while read filename count
do
    count_dt=$(date "+%Y-%m-%d %H:%M:%S")
    echo "db|Abhi_Ram|record_count|${filename}||${count}||${count_dt}"
done <sample.txt >>output.txt

这将产生文件:

$ cat output.txt 
db|Abhi_Ram|record_count|2015-03-04.01.Abhi_Ram.json||10||2015-08-10 14:42:39
db|Abhi_Ram|record_count|2015-03-04.02.Abhi_Ram.json||70||2015-08-10 14:42:39

注意:

  1. 对于壳变量,最好使用小写或混合大小写。系统使用大写变量,并且您不想意外覆盖一个变量。

  2. echo语句中的许多双引号是不必要的。整个输出字符串可以在一个双引号字符串内。

  3. 如果您想一次读取一行文件,使用while read ... done <inputfile构造会更安全。 read语句还使我们可以轻松定义filenamecount变量。

  4. 对于命令替换,许多人都喜欢$(...)形式而不是反引号形式。这是因为(a)$(...)使命令替换的开始和结束在视觉上是不同的;(b)$(...)格式嵌套得很好,并且(c)并非所有字体都清楚地显示出反引号与常规的勾号不同。 (感谢Chepner。)

  5. 为了提高效率,重定向到output.txt的位置已移至循环的末尾。这样,该文件仅打开和关闭一次。 (感谢查尔斯·达菲。)

  6. 除非您需要使用每个单独的条目更新count_dt,否则可以将其放置在循环之前,并在每次处理sample.txt时仅设置一次。如果您具有bash的最新版本(无Mac OSX),则可以用本机bash语句(无需脱壳)替换count_dt分配(谢谢Charles Duffy):

    printf -v count_dt '%(%Y-%m-%d %H:%M:%S)T'
    

2
投票

John1024已经解释了如何正确执行此操作;我想看看为什么原始版本不起作用。基本问题是forwords而不是行上循环。该文件每行有两个单词(文件名和计数),因此它每行两次运行循环。要查看此内容,请尝试:

for line in `hadoop fs -cat sample.txt`
do
    echo "$line"
done

...它会打印类似:

2015-03-04.01.Abhi_Ram.txt
10
2015-03-04.02.Abhi_Ram.txt
70

...这根本不是您想要的。它还有一些其他令人不愉快的问题,例如输入文件中包含单词“ *”,它将在当前目录中插入文件名列表。

while read ... done <file方法是在Shell脚本中迭代行的正确方法。它恰好也能够将每一行划分为多个字段,而不必弄乱awk(在这种情况下,read filename count会这样做)。

© www.soinside.com 2019 - 2024. All rights reserved.