我想在同一行上回显两个变量。我想将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 ||||时间戳
有人可以指出我所缺少的东西吗?
考虑:
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
注意:
对于壳变量,最好使用小写或混合大小写。系统使用大写变量,并且您不想意外覆盖一个变量。
echo
语句中的许多双引号是不必要的。整个输出字符串可以在一个双引号字符串内。
如果您想一次读取一行文件,使用while read ... done <inputfile
构造会更安全。 read
语句还使我们可以轻松定义filename
和count
变量。
对于命令替换,许多人都喜欢$(...)
形式而不是反引号形式。这是因为(a)$(...)
使命令替换的开始和结束在视觉上是不同的;(b)$(...)
格式嵌套得很好,并且(c)并非所有字体都清楚地显示出反引号与常规的勾号不同。 (感谢Chepner。)
为了提高效率,重定向到output.txt
的位置已移至循环的末尾。这样,该文件仅打开和关闭一次。 (感谢查尔斯·达菲。)
除非您需要使用每个单独的条目更新count_dt
,否则可以将其放置在循环之前,并在每次处理sample.txt
时仅设置一次。如果您具有bash的最新版本(无Mac OSX),则可以用本机bash语句(无需脱壳)替换count_dt
分配(谢谢Charles Duffy):
printf -v count_dt '%(%Y-%m-%d %H:%M:%S)T'
John1024已经解释了如何正确执行此操作;我想看看为什么原始版本不起作用。基本问题是for
在words而不是行上循环。该文件每行有两个单词(文件名和计数),因此它每行两次运行循环。要查看此内容,请尝试:
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
会这样做)。