it-swarm.com.ru

Эхо нескольких переменных в одной строке Bash

Я хочу отобразить две переменные в одной строке.
Я хочу хранить 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 |||| метка времени
дб | Abhi_Ram | record_count | 10 |||| метка времени
дб | Abhi_Ram | record_count | 2015-03-04.02.Abhi_Ram.txt |||| метка времени
дб | Abhi_Ram | record_count | 70 |||| метка времени 

Может ли кто-нибудь указать мне, что мне не хватает?

6
AS0207

Рассматривать:

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. Система использует переменные верхнего регистра, и вы не хотите случайно перезаписывать ее.

  2. Многие двойные кавычки в выражении echo были ненужными. Вся выходная строка может быть внутри одной строки в двойных кавычках.

  3. Если вы хотите прочитать файл по одной строке за раз, безопаснее использовать конструкцию while read ... done <inputfile. Оператор read также позволяет нам легко определять переменные filename и count.

  4. Для подстановки команд многие предпочитают форму $(...) формам с обратной связью. Это связано с тем, что (a) функция $(...) визуально различает начало и конец подстановки команд, (b) форма $(...) хорошо вкладывается, и (c) не все шрифты четко показывают обратные метки в отличие от обычных тиков. (Спасибо, Чепнер.)

  5. Для эффективности перенаправление на output.txt было перенесено в конец цикла. Таким образом, файл открывается и закрывается только один раз. (Спасибо Чарльз Даффи.)

  6. Если вам не нужно обновлять count_dt с каждой отдельной записью, его можно поместить перед циклом и устанавливать только один раз при обработке sample.txt. Если у вас установлена ​​последняя версия bash (без Mac OSX), то назначение count_dt можно заменить (спасибо Charles Duffy) на собственное выражение bash (не требует выделения):

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

Джон 1024 объяснил, как сделать это правильно; Я хотел бы взглянуть на то, почему оригинальная версия не работает. Основная проблема в том, что 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

... что совсем не то, что вы хотите. У него также есть некоторые другие неприятные особенности: например, если входной файл содержит слово «*», он вставит список имен файлов в текущем каталоге.

Подход while read ... done <file - это правильный способ перебора строк в сценарии Shell. Так же бывает, что можно разделить каждую строку на поля без необходимости связываться с awk (в этом случае read filename count делает это).

2
Gordon Davisson