-3

Да, прежде чем кто-то вскочит и нападет на меня вилой, это двойной вопрос, но другие не работают для меня, поэтому я задаю его сам сейчас.

У меня есть файл CSV, у которого есть даты где-то в каждой записи. Дополнительная трудность при конвертации заключается в том, что иногда даты будут иметь однозначные числа в течение нескольких дней. Пример записи:

abc,0,2,-2,3-16-1994
xyz,1,2,3,10-09-1994

Я хочу, чтобы что-то, предпочтительно sed, конвертировало эти записи данных так:

abc,0,2,-2,1994-03-16
xyz,1,2,3,1994-09-10

Я пробовал:

sed 's|(..)-(..)-(....)|\3-\2-\1|'

Но это дает ошибку, и она на самом деле не охватывает однодисковые проблемы дня.

Я также попробовал:

awk -F - '{print $3$2$1}'

Это на самом деле имеет некоторый желаемый эффект, но опять же не совсем. Команда awk преобразует его, но только месяц и год, и вместо того, чтобы поставить дату назад, где она была, она помещает месяц и год начала строки, оставляя часть дня, где бы она ни находилась.

Любая помощь будет потрясающей!

Заранее спасибо.

редактировать

В комментариях было правильно указано, что я допустил ошибку в своих примерах. Даты должны быть:

abc,0,2,-2,16-03-1994
xyz,1,2,3,2-05-1994

С желаемым результатом:

abc,0,2,-2,1994-03-16
xyz,1,2,3,1994-05-02

Извините ребята.

2 ответа2

1

sed -r 's/(\d{1,2})-([0-9]{2})-([0-9]{4})/\3-\2-\1/g' кажется чтобы добиться цели, могут быть и другие "умные" способы ... Я не знаю

мой код:

x="abc,0,2,-2,3-16-1994#xyz,1,2,3,10-09-1994"
echo $x |tr '#' '\n'| sed -r 's/([0-9]{1,2})-([0-9]{2})-([0-9]{4})/\3-\2-\1/g'

производит:

abc,0,2,-2,1994-16-3
xyz,1,2,3,1994-09-10

2 "предупреждения" для ваших данных ... немного противоречиво (возможно, это было только для примера) ...

  • в первой строке первый элемент даты не дополняется нулями
  • после просмотра второй строки неясно, являются ли входные данные dd-mm-yyyy или mm-dd-yyyy

Позже редактирование: я сначала пропустил ту часть, что заполнение дня было требованием, учитывая это, кажется, что следующее помогает

echo $x |tr '#' '\n'| sed -r 's/\b([0-9])-([0-9]{2})-([0-9]{4})\b/\3-\2-0\1/g; s/\b([0-9]{2})-([0-9]{2})-([0-9]{4})\b/\3-\2-\1/g'

практически у нас есть 2 регулярных выражения, одно (первое) соответствует "датам", где день имеет только 1 цифру, и добавляет подстановку "0" при выполнении подстановки, другое соответствует "датам", которые имеют день с 2 цифрами, и выполняет только переупорядочение элементов

идея пришла отсюда https://stackoverflow.com/questions/12129382/add-leading-0-in-sed-substitution, так что слава человеку, который там ответил

0

Это работает, когда я проверяю его, обратите внимание, что я поменял день и месяц, так как исходный формат в вашем примере на самом деле mm-dd-yyy. Не уверен, важен ли для вас нулевой отступ, не пробовал:

sed -i -r 's|([[:digit:]]*)-([[:digit:]]*)-([[:digit:]]*)|\3-\1-\2|' test.csv

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .