Таблицы переформатирования

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

http://pune.cdac.in/html/ суть / вниз / key.asp

1
задан 14 August 2015 в 15:36

3 ответа

Это было бы заданием для 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

Или, сокращенно с использованием ERE (спасибо пользователю1598390):

sed -E -i.bak 's/.*([0-9]{4})-[0-9]{2}-([0-9]{2})(.*)/\1\t\2\3/' infile
-i.bak: обрабатывает файл на месте, резервное копирование исходного файла на infile.bak

sed:

-i.bak: обрабатывает файл на месте, резервное копирование исходного файла на infile.bak / : запускает шаблон [^\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
7
ответ дан 23 May 2018 в 18:13
  • 1
    Спасибо за ваш ответ и все прилагаемое объяснение! Я новичок, и благодаря этому я многому учусь! К сожалению, когда я использую эту команду (при условии, что мой входной файл называется «infile.txt») [sed -i.bak 's / ([^ \ t] *) \ t ([^ -] *) [^ \ t ] * \ t ([^ \ t] *) / \ 2 \ t \ 1 \ t \ 3 / 'infile.txt] входной файл остается неизменным, а созданный * .bak совпадает с входным файлом. Я уверен, что чего-то не хватает! – steve 14 August 2015 в 14:37
  • 2
    @steve Вероятно, ваш файл немного отличается от приведенного вами примера, например, даже пробел (или случайная табуляция) в конце каждой строки сломает его. Вы уверены, что в конце концов ничего нет? Однако ответ хаоса way более изящный, так как awk является инструментом для этого – kos 14 August 2015 в 14:44
  • 3
    Я сделал глупую ошибку, моя вина! Большое вам спасибо за помощь и преподавание в то же время;) – steve 14 August 2015 в 14:47
  • 4
    @steve Нет проблем :) Ждите хаоса, чтобы обновить его ответ жестко, потому что на данный момент (как первая версия моего ответа) он не меняет вывод второго столбца на основе дня, а на идентификаторе, который выглядит как , это не то, что вы хотите – kos 14 August 2015 в 14:51
  • 5
    Да, ты прав! День подходит для ID, и мне хотелось бы, чтобы этот день соответствовал соответствующим дням соответствующих лет! – steve 14 August 2015 в 15:08

Используйте 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
1
ответ дан 23 May 2018 в 18:13
  • 1
    Действительно, substr. И во всяком случае лучше, чем мой ответ. Единственная проблема - этот комментарий и комментарий ниже, который я также не видел сначала: | – kos 14 August 2015 в 14:41

Использование только bash:

#!/bin/bash
shopt -s extglob
printf "YYYY\tDDD\tsim\n"
while IFS=$'\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, чтобы получить желаемый шаблон вывода. Ознакомьтесь с расширением параметра из документа GNU. extglob используется для удаления заполненных нулей из дней.

Пример:

Пример:

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
1
ответ дан 23 May 2018 в 18:13

Другие вопросы по тегам:

Похожие вопросы: