在同一行Bash

时间:2015-08-10 21:37:41

标签: linux bash hadoop echo

我想在同一行回应两个变量 我想将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

有人能指出我缺少的东西吗?

2 个答案:

答案 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

注意:

  1. 最佳做法是对shell变量使用lower或mixed case。系统使用大写变量,您不希望意外覆盖一个。

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

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

  4. 对于命令替换,许多人更喜欢使用反引号形式的$(...)形式。这是因为(a)$(...)使命令替换的开始和结束在视觉上不同,(b)$(...)形式嵌套良好,(c)并非所有字体都清楚地显示反引号与定期蜱虫。 (谢谢切普纳。)

  5. 为了提高效率,重定向到output.txt已移至循环结束。这样,文件只能打开和关闭一次。 (感谢Charles Duffy。)

  6. 除非您需要为每个条目更新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会这样做。)