我想在同一行回应两个变量 我想将2015-03-04.01.Abhi_Ram.txt存储在变量FILENAME中,将10存储在变量COUNT中并同时回显它们。
Sample.txt
2015-03-04.01.Abhi_Ram.txt 10
2015-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:
分贝| Abhi_Ram | record_count | 2015-03-04.01.Abhi_Ram.txt || || 10时间戳 分贝| Abhi_Ram | record_count | 2015-03-04.02.Abhi_Ram.txt || || 70时间戳
I'm getting the output as:
分贝| 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 |||| timestamp
有人能指出我缺少的东西吗?
答案 0 :(得分:9)
考虑:
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
注意:
最佳做法是对shell变量使用lower或mixed case。系统使用大写变量,您不希望意外覆盖一个。
echo
声明中的许多双引号是不必要的。整个输出字符串可以在一个双引号字符串中。
如果您想一次读取一行文件,使用while read ... done <inputfile
构造会更安全。 read
语句还允许我们轻松定义filename
和count
变量。
对于命令替换,许多人更喜欢使用反引号形式的$(...)
形式。这是因为(a)$(...)
使命令替换的开始和结束在视觉上不同,(b)$(...)
形式嵌套良好,(c)并非所有字体都清楚地显示反引号与定期蜱虫。 (谢谢切普纳。)
为了提高效率,重定向到output.txt
已移至循环结束。这样,文件只能打开和关闭一次。 (感谢Charles Duffy。)
除非您需要为每个条目更新count_dt
,否则可以将其放在循环之前,并在每次处理sample.txt
时设置一次。如果你有一个最新版本的bash(没有Mac OSX),那么count_dt
赋值可以用原生bash语句替换(感谢Charles Duffy)(不需要炮轰):
printf -v count_dt '%(%Y-%m-%d %H:%M:%S)T'
答案 1 :(得分:2)
John1024已经解释了如何正确地做到这一点;我想看一看为什么原版本没有用。基本问题是for
遍历单词,而不是通过行。该文件在每一行上有两个单词(文件名和计数),因此每行运行两次循环。要看到这一点,请尝试:
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
......这根本不是你想要的。它还有一些其他令人不快的怪癖,比如输入文件包含单词&#34; *&#34;,它会在当前目录中插入文件名列表。
while read ... done <file
方法是在shell脚本中迭代行的正确方法。它恰好也能够将每一行拆分成字段而不必混淆awk
(在这种情况下,read filename count
会这样做。)