У меня есть следующий тип таблиц:
ID date DailyFlow
a 1972-01-01 17.0265761797993
b 1972-01-02 17.200476457399
c 1972-01-03 17.2926436045271
d 1972-01-04 17.3900277599829
e 1972-01-05 17.5987080931028
f 1972-01-06 17.6334881486229
g 1972-01-07 17.7030482596626
...
Я хотел бы переформатировать их следующим образом:
YYYY DDD sim
1972 1 17.0265761797993
1972 2 17.200476457399
1972 3 17.2926436045271
1972 4 17.3900277599829
1972 5 17.5987080931028
1972 6 17.6334881486229
1972 7 17.7030482596626
1972 8 17.7204382874227
Первая строка содержится в таблицах. Файлы представляют собой обычный текст (* .txt) с разделителем «табуляция». Столбец ID - фиктивная, от которой я бы хотел избавиться! В моем желаемом выводе числа (1,2,3, ...) в столбце DDD должны совпадать с днем соответствующих лет.
Есть ли у кого-нибудь идеи о том, как это сделать (используя bash)? Спасибо!
Используя awk
для парсинга и date
отформатировать дату, что еще ;)
awk 'BEGIN {printf "%s\t%s\t%s\n","YYYY","DDD","sim"} NR != 1 {system("date -d \""$2"\" +\"%Y\t%-d\t"$3"\"")}' your_file
Показать день года (использование %j
вместо %d
или лучше %-j
вместо %-d
, -
старается не вести 0
)
awk 'BEGIN {printf "%s\t%s\t%s\n","YYYY","DDD","sim"} NR != 1 {system("date -d \""$2"\" +\"%Y\t%-j\t"$3"\"")}' your_file
Пример
Входной файл
% cat foo
ID date DailyFlow
a 1972-01-01 17.0265761797993
b 1972-01-02 17.200476457399
c 1972-01-03 17.2926436045271
d 1972-01-04 17.3900277599829
e 1972-01-05 17.5987080931028
f 1972-01-06 17.6334881486229
g 1972-01-07 17.7030482596626
h 1972-02-01 17.7030482596626
i 1972-02-02 17.7030482596626
Вывод (со днем месяца)
% awk 'BEGIN {printf "%s\t%s\t%s\n","YYYY","DDD","sim"} NR != 1 {system("date -d \""$2"\" +\"%Y\t%-d\t"$3"\"")}' foo
YYYY DDD sim
1972 1 17.0265761797993
1972 2 17.200476457399
1972 3 17.2926436045271
1972 4 17.3900277599829
1972 5 17.5987080931028
1972 6 17.6334881486229
1972 7 17.7030482596626
1972 1 17.7030482596626
1972 2 17.7030482596626
Вывод (со днем года)
% awk 'BEGIN {printf "%s\t%s\t%s\n","YYYY","DDD","sim"} NR != 1 {system("date -d \""$2"\" +\"%Y\t%-j\t"$3"\"")}' foo
YYYY DDD sim
1972 1 17.0265761797993
1972 2 17.200476457399
1972 3 17.2926436045271
1972 4 17.3900277599829
1972 5 17.5987080931028
1972 6 17.6334881486229
1972 7 17.7030482596626
1972 32 17.7030482596626
1972 33 17.7030482596626
Используйте awk
:
awk 'BEGIN{print "YYYY\tDDD\tsim"} NR!=1{printf "%s\t%s\t%s\n",substr($2,0,5),$1,$3}' file
Объяснение
BEGIN{}
часть форматирует строку заголовка. NR!=1
опускает строку заголовка Ваших форматов файла printf()
, вывод substr($2,0,5)
удаляет день и месяц с даты выходные взгляды:
YYYY DDD sim
1972 1 17.0265761797993
1972 2 17.200476457399
1972 3 17.2926436045271
1972 4 17.3900277599829
1972 5 17.5987080931028
1972 6 17.6334881486229
1972 7 17.7030482596626
Используя только bash
:
#!/bin/bash
shopt -s extglob
printf "YYYY\tDDD\tsim\n"
while IFS= -
Мы читаем каждую строку входного файла, начинающего со второй строки, и помещающий вкладку разделил части как переменную first
, second
, и third
последовательно
-
Затем мы используем bash
расширение параметра для получения нашего желаемого выходного шаблона. Читайте о расширении параметра от , документ .
-
extglob
GNU используется для удаления заполненного, обнуляет со дней.
Пример:
Вход:
ID date DailyFlow
a 1972-01-01 17.0265761797993
b 1972-01-02 17.200476457399
c 1972-01-03 17.2926436045271
d 1972-01-04 17.3900277599829
e 1972-01-05 17.5987080931028
f 1972-01-06 17.6334881486229
g 1972-01-07 17.7030482596626
h 1972-02-01 17.7030482596626
i 1972-02-02 17.7030482596626
Вывод:
YYYY DDD sim
1972 1 17.0265761797993
1972 2 17.200476457399
1972 3 17.2926436045271
1972 4 17.3900277599829
1972 5 17.5987080931028
1972 6 17.6334881486229
1972 7 17.7030482596626
1972 32 17.7030482596626
1972 33 17.7030482596626
\t' read -r first second third; do
day="$(date --date="$second" '+%j')"
printf "%s\t%s\t%s\n" "${second%%-*}" "${day##*(0)}" "${third}"
done < <(tail -n +2 foo.txt)
Мы читаем каждую строку входного файла, начинающего со второй строки, и помещающий вкладку разделил части как переменную first
, second
, и third
последовательно
Затем мы используем bash
расширение параметра для получения нашего желаемого выходного шаблона. Читайте о расширении параметра от , документ .
extglob
GNU используется для удаления заполненного, обнуляет со дней.
Пример:
Вход:
ID date DailyFlow
a 1972-01-01 17.0265761797993
b 1972-01-02 17.200476457399
c 1972-01-03 17.2926436045271
d 1972-01-04 17.3900277599829
e 1972-01-05 17.5987080931028
f 1972-01-06 17.6334881486229
g 1972-01-07 17.7030482596626
h 1972-02-01 17.7030482596626
i 1972-02-02 17.7030482596626
Вывод:
YYYY DDD sim
1972 1 17.0265761797993
1972 2 17.200476457399
1972 3 17.2926436045271
1972 4 17.3900277599829
1972 5 17.5987080931028
1972 6 17.6334881486229
1972 7 17.7030482596626
1972 32 17.7030482596626
1972 33 17.7030482596626
This был бы заданием для я закончил с awk
, но замена во втором столбце потребует gensub
и следовательно gawk
, который не установлен по умолчанию, таким образом sed
решение:
sed -i.bak 's/[^\t]*\t\([^-]*\)-[0-9][0-9]-[0-9]\([0-9]\)[^\t]*\t\([^\t]*\)/\1\t\2\t\3/' infile
Или, сокращенное использование EREs (благодаря user1598390):
sed -E -i.bak 's/.*([0-9]{4})-[0-9]{2}-([0-9]{2})(.*)/\1\t\2\3/' infile
-i.bak
: обрабатывает файл на месте, создавая резервную копию исходного файла к infile.bak
sed
разбивка команды:
s
: утверждает для выполнения замены; /
: запускает шаблон [^\t]*
: соответствия любое количество любого символа не \t
; \t
: соответствует \t
символ \(
: запускает первую группу фиксации [^-]*
: соответствия любое количество любого символа не -
; \)
: останавливает первую группу фиксации -
: соответствует -
символ [0-9]
: соответствия любая цифра [0-9]
: соответствия любая цифра -
: соответствует -
символ [0-9]
: соответствия любая цифра \(
: запускает вторую группу фиксации [0-9]
: соответствия любая цифра \)
: останавливает вторую группу фиксации [^\t]*
: соответствия любое количество любого символа не \t
; \t
: соответствует \t
символ \(
: запускает третью группу фиксации [^\t]*
: соответствия любое количество любого символа не \t
; \)
: останавливает третью группу фиксации /
: останавливается шаблон / запускает замещающую строку \1
: обратная ссылка заменяется первой группой фиксации \2
: обратная ссылка заменяется второй группой фиксации \3
: обратная ссылка заменяется третьей группой фиксации /
: останавливается замещающая строка / запускает модификаторы Вывод для файла примера:
user@debian ~/tmp % cat infile
a 1972-01-01 17.0265761797993
b 1972-01-02 17.200476457399
c 1972-01-03 17.2926436045271
d 1972-01-04 17.3900277599829
e 1972-01-05 17.5987080931028
f 1972-01-06 17.6334881486229
g 1972-01-07 17.7030482596626
user@debian ~/tmp % sed 's/[^\t]*\t\([^-]*\)-[0-9][0-9]-[0-9]\([0-9]\)[^\t]*\t\([^\t]*\)/\1\t\2\t\3/' infile
1972 1 17.0265761797993
1972 2 17.200476457399
1972 3 17.2926436045271
1972 4 17.3900277599829
1972 5 17.5987080931028
1972 6 17.6334881486229
1972 7 17.7030482596626