2014-01-14 3 views
1

Привет, я пытаюсь вывести файл CSV, и я продолжаю получать часть своей строки, написанную на новой строке.Неожиданная новая строка при написании в Unix Shell Script

Общий сценарий читается в CSV-файле, который имеет метку времени, преобразует его, а затем добавляет время Epoch к концу строки в качестве новой переменной и выводит файл.

#!/bin/bash 
OLDIFS=$IFS 
IFS="," 
cat test.csv | while read Host AName Resource MName TimeStamp Integer_Value Epoch; 
do 

Epoch=$(date -d "$TimeStamp GMT" +%s) 

if [ -z "$Epoch" ] 
then 
    (echo "$Host, $AName, $Resource, $MName, $TimeStamp, $Integer_Value, Epoch,";) >> target.csv 

else 
    (echo "$Host, $AName, $Resource, $MName, $TimeStamp, $Integer_Value, $Epoch,";) >> target.csv 

fi 

done 

Я пытаюсь установить заголовок, то выписывать прилагаемые переменный, ожидать, и это происходит только на новом значении, она падает прилагаемые переменную в новую строку.

#Host, AName, Resource, MName, Actual Start Time, Integer Value 
, Epoch, 
ABCD89A, Admin, shop, Stall Count, 2014-01-06 09:00:00.0, 0 
, 1388998800, 

Вместо

#Host, AName, Resource, MName, Actual Start Time, Integer Value, Epoch, 
ABCD89A, Admin, shop, Stall Count, 2014-01-06 09:00:00.0, 0, 1388998800, 

Когда я двигаю порядок вокруг него не бывает. Извините, я знаю, что это, наверное, просто я новичок в сценариях Unix.

EDIT

Теперь я изменил код:

#!/bin/bash 
OLDIFS=$IFS 
IFS="," 
while read Host AName Resource MName TimeStamp Integer_Value Epoch 
do 

Epoch=$(date -d "$TimeStamp GMT" +%s) 

if [ -z "$Epoch" ] 
then 
    echo "$Host, $AName, $Resource, $MName, $TimeStamp, $Integer_Value, Epoch," 

else 
    echo "$Host, $AName, $Resource, $MName, $TimeStamp, $Integer_Value, $Epoch," 

fi 

done <test.csv> target.csv 

И я все еще получаю те же проблемы.

также как дополнительный вопрос, если кто-нибудь знает, почему я получаю: команда не найдена дата: неверная дата `Фактическое время начала TimeStamp GMT 'при запуске части даты, но она дает правильную дату и запускает скрипты.

+1

Попробуйте удалить все полуколоны и скобки вокруг инструкций «эхо». Затем удалите «cat test.csv» и добавьте «>» и добавьте «> target.csv» после «done». –

+0

Привет, Марк, спасибо за ваш ответ, я пробовал, что это не имеет значения, все равно это происходит. – QuinsUK

+0

Запустили ли вы скрипт с 'bash -x script'? Недействительные сообщения о сообщениях удивляют; 'bash -x' будет (должен) показывать, какой вызов команды' date' генерирует сообщение. Новая линия немного озадачивает. Я предлагаю попробовать 'IFS = $ ', \ n''. Если это работает, то объяснение состоит в том, что 'read' включает в себя новую строку во входной строке, но, исключая новую строку из IFS, вы запрещаете оболочке игнорировать новую строку. –

ответ

1

Попробуйте этот скрипт:

IFS=[,$'\r']; while read Host AName Resource MName TimeStamp Integer_Value Epoch 
do 
    # ignore first line with headers 
    [[ "$Host" == \#* ]] && continue 

    Epoch=$(date -d "$TimeStamp GMT" +%s) 

    if [ -z "$Epoch" ]; then 
    echo "$Host, $AName, $Resource, $MName, $TimeStamp, $Integer_Value, Epoch," 
    else 
    echo "$Host, $AName, $Resource, $MName, $TimeStamp, $Integer_Value, $Epoch,"  
    fi 
done <test.csv> target.csv 

Это делает 2 вещи по-разному:

  1. Он обрабатывает \r как разделитель полей и не включает в себя переменные чтения
  2. Он игнорирует ваш первый li ne, который является заголовком входного CSV-файла
0

Я бы лично использовать AWK вот как:

awk -F"," '{timestamp=$5; gsub(":"," ",timestamp); gsub("-"," ",timestamp); EPOCH=(mktime(timestamp)*1000)} {print $0","EPOCH}' 1.csv 

Производит:

ABCD89A, Admin, shop, Stall Count, 2014-01-06 09:00:00, 0,1388998800000 

A 1 вкладыш, который делает все, что вам нужно:

Так долго, как ваши временные штампы находятся в этом точном формате, тогда gsum в awk remvoving: и - из формата даты, передающего его в mktime, для создания метки времени в секундах и, наконец, для печати каждой строки полностью $ 0 "," EPOCH, которая теперь c значение инвертированного времени

awk -F"," '{ 
    timestamp=$5; 
    gsub(":"," ",timestamp); 
    gsub("-"," ",timestamp); 
    EPOCH=(mktime(timestamp)*1000) 
    } 
    { 
     print $0","EPOCH 
     }' your_File.csv 

Здесь он расширен.

Теперь, чтобы расширить это так, что вы читаете этот файл разбора через AWK, а затем перекачать выход обратно в тот же файл, который вы могли бы что-то вроде этого:

cp 2.csv 1.csv 
cat 1.csv 
ABCD89A, Admin, shop, Stall Count, 2014-01-06 09:00:00, 0 
ABCD89N, Admin, shop, Stall Count, 2014-01-06 09:00:00, 0 
file="1.csv"; output=$(awk -F"," '{ timestamp=$5;gsub(":"," ",timestamp);gsub("-"," ",timestamp);EPOCH=(mktime(timestamp));}{print $0", "EPOCH;}' $file 2>&1); echo "$output" > $file 
cat 1.csv 
ABCD89A, Admi , shop, Stall Cou t, 2014-01-06 09:00:00, 0, 1388998800 
ABCD89N, Admi , shop, Stall Cou t, 2014-01-06 09:00:00, 0, 1388998800 

Теперь расширить этот метод, так что вы обеспечиваете вы не перезаписывать тот же файл, который уже был установлен со временем в секундах вы можете запустить что-то вроде этого:

cp 2.csv 1.csv 
cat $file 
ABCD89A, Admin, shop, Stall Count, 2014-01-06 09:00:00, 0 
ABCD89N, Admin, shop, Stall Count, 2014-01-06 09:00:00, 0 
file="1.csv"; output=$(awk -F"," '{ if (NF==7) { print "ERROR"; next; }else{timestamp=$5;gsub(":"," ",timestamp);gsub("-"," ",timestamp);EPOCH=(mktime(timestamp));}{print $0", "EPOCH;}}' $file 2>&1); if echo "$output"|grep -q "ERROR"; then echo "$output"; else echo "$output" > $file; fi 
file="1.csv"; output=$(awk -F"," '{ if (NF==7) { print "ERROR"; next; }else{timestamp=$5;gsub(":"," ",timestamp);gsub("-"," ",timestamp);EPOCH=(mktime(timestamp));}{print $0", "EPOCH;}}' $file 2>&1); if echo "$output"|grep -q "ERROR"; then echo "$output"; else echo "$output" > $file; fi 
ERROR 
ERROR 
cat $file 
ABCD89A, Admin, shop, Stall Count, 2014-01-06 09:00:00, 0, 1388998800 
ABCD89N, Admin, shop, Stall Count, 2014-01-06 09:00:00, 0, 1388998800 

вы заметите на 2-м ходу он выводит сообщение об ошибке и на самом деле не перезаписать тот же файл. ..

Таким образом, вы можете автоматизировать некоторые сценарии, чтобы прийти и сделать это и чувствовать себя в безопасности, что это не добавит дополнительный материал к существующим CSV-

Или использовать временный файл для массивных файлов CSV: Это бессмысленно line I Я только тестировал, могу ли я вернуться обратно в тот же файл, который, как я нашел, работал в нечетных случаях - действительно, bizzare.

(awk -F"," '{ timestamp=$5;gsub(":"," ",timestamp);gsub("-"," ",timestamp);EPOCH=(mktime(timestamp));}{print $0", "EPOCH;}' 1.csv 2>&1|tee /tmp/a; mv /tmp/a 1.csv;) 

, так как это могло бы только что был

(awk -F"," '{ timestamp=$5;gsub(":"," ",timestamp);gsub("-"," ",timestamp);EPOCH=(mktime(timestamp));}{print $0", "EPOCH;}' 1.csv >/tmp/a; mv /tmp/a 1.csv;) 

Первый метод с использованием $ выходных сохраняет в формате CSV в память в качестве переменной, а затем выталкивает обратно в файл. Второй или последний метод, вероятно, самая последняя попытка файла/tmp использует временный файл для обработки. Выбранный вами метод может зависеть от размера вашего CSV-файла. Если мы говорим о концертах и ​​не очень мощной машине, то временные файлы - это путь. Память явно чище и должна быть самой быстрой.

Его только мой вклад в это - она ​​может пригодиться для кого-то другого желающего сделать что-то подобное

+0

Спасибо за ваш ответ, как бы вы использовали awk? К сожалению, это еще не помогло, но у него все те же проблемы. – QuinsUK

+0

Я обновил ответ, чтобы использовать 1 лайнер в awk для создания того, что вам нужно. – Vahid

Смежные вопросы