LINUX.ORG.RU

Редактирование потока с просмотром вперёд.

 ,


0

1

Дано: Csv для обработки со строками вида: «что-то_1|ПЕРЕМЕННАЯ|что-то_2», где ПЕРЕМЕННАЯ - одна ИЛИ ДВЕ даты в формате: «dd.dd.dddd»

Задача:

Если строка вида: «что-то_1|дата|другая_дата|что-то_2» - оставить как есть.

Если строка вида: «что-то_1|дата|что-то_2», то заменить: «что-то_1|дата|текст|что-то_2», где «текст» определён заранее (нет даты).

Из вики по регэкспам: (?!шаблон) - Негативный просмотр вперёд.

В sed этот метод не работает (у меня даже с ключом -r), а с другими языками обработки потока пока что плохо знаком... Чем можно решить эту задачу?

★★
Ответ на: комментарий от anonymous

awk:

awk -F'|' -v OFS='|' \
	'{ if(NF == 3) { print $1, $2, "текст", $3 } else { print $0 } }'

anonymous
()
Ответ на: комментарий от anonymous

sed -r 's/^([^\|]+)\|([^\|]+)\|([^\|]+)$/\1|\2|текст|\3/'

Данный sed будет шарашить «текст» во все строки подряд. Или я не прв?

zzdnx ★★
() автор топика
Последнее исправление: zzdnx (всего исправлений: 1)

Решил кастыльно.

Сначала grep`ом разбил файл на две части, потом обработал одну из них sed`ом, после чего слил два куска и пропустил это через sort | uniq.

zzdnx ★★
() автор топика
Ответ на: комментарий от zzdnx

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

/^[^\|]*\|[^\|]*\|[^\|]*$/
Для них выполняй замену (добавляй текст третьим полем).

Первый пост анонимуса об этом. Второй - более понятное решение с помощью awk. Правда, ни в одном из этих решений нет проверки на то что второе поле именно дата в указанном тобой формате. Если надо - добавь проверку, это не сложно.

Просмотр вперед здесь ни при чем.

ksv
()
Последнее исправление: ksv (всего исправлений: 1)
Ответ на: комментарий от ksv

В том-то и проблема. Дата не является крайним полем, и в документе нет строк с тремя полями вообще - в каждой строке по 5-7 полей. Задача состоит именно в том, чтобы залезть в середину строки, найти (по шаблону) от начала строчки первую дату и посмотреть - а есть-ли вторая дата следом за первой? Если дата есть - пропускаем, а если нет - вставляем после первой даты новое поле с текстом (об отсутствии даты в оригинале файла).

Доп-условия:

Поле, в котором встречается первая от начала строки дата не может быть на первом месте (это номер строки), или на последним месте (там ссылка вида \\server\public\...\...\), однако оно может «плавать» - быть на втором или третьем, а может, на четвёртом месте. В таких условиях sed -r 's/^([^\|]+)\|([^\|]+)\|([^\|]+)$/\1|\2|текст|\3/' не применимо.

Я потому и решился на «негативный просмотр вперёд» - чтобы не просто детектировать строку с датой, а чтобы на лету определять строки с одной датой вместо двух подряд, ну, и, править их, разумеется.

Расчитывал на что-то такое:

sed 's/^\(.*\)\(`DATA1`|\(?!`DATA2`|\)\)\(.*\)/\1\2текст|\3/g'

zzdnx ★★
() автор топика
Последнее исправление: zzdnx (всего исправлений: 2)
Ответ на: комментарий от zzdnx

Ну так надо сразу же формулировать все ограничения.

Должно помочь что-то в этом духе:

sed -r '/..\...\.....\|..\...\...../! {s/(\|..\...\.....\|)/\1text\|/}'

Применение команды s - на строках, где нет двух подряд идущих дат. Для всех таких строк применяется команда - первая дата заменяется на дату с текстом.

PS Мне лень прописывать ограничения на дату, но везде где стоит . без экранирования должно быть [0-9].

ksv
()
Ответ на: комментарий от ksv

На сколько я понимаю, это работа с подстрокой. Спасибо за помощь! Так же нашёл на этом ресурсе упоминание о том, что в sed позитивный|негативный просмотр вперёд|назад не реализован.

sed - regex - позитивный/негативный просмотр вперед/назад

zzdnx ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.