awk sed обратная ссылка CSV-файл - PullRequest
0 голосов
/ 15 декабря 2018

Вопрос о расширении предыдущего здесь .(Я предпочитаю задавать новый вопрос, а не редактировать первый. Я могу ошибаться)

РЕДАКТИРОВАТЬ: хорошо, я был не прав, я должен отредактировать свой первый вопрос.Мой плохой (ТАК вопрос - искусство, которое трудно освоить)

У меня есть CSV-файл с полуколонкой в ​​качестве разделителя полей.Вот выдержка из CSV-файла:

...;field;(:);10000(n,d);(:);field;.... ...;field;123.12(b);123(a);123.00(:);....

Вот желаемый вывод:

...;field;(:);(n,d) 10000;(:);field;.... ...;field;(b) 123.12;(a) 123;(:) 123.00;....

Я ищу решение для обмена2 шаблона в каждом поле.

шаблон 1: любая цифра с необязательной десятичной отметкой (.) И необязательной десятичной цифрой

, например: 1 / 1111.00 / 444444444.3 / 32 / 32.6666666 / 1.0 /....

шаблон 2: любая строка, которая начинается с левой круглой скобки, за которой следует один или несколько символов, заканчивающихся правой круглой скобкой

, например: (n, a, p) / (:)/ (llll) / (d) / (123) / (1; 2; 3) ...

Решения, представленные в первом вопросе, подходят для простого файла, который содержит только один столбец.Если я попробую решение в файле csv, я столкнусь с несколькими сбоями.

Поэтому я пытаюсь awk подобное решение, которое (я думаю) более "ориентировано на столбцы".

У меня естьпопробуйте

awk -F";" '{print gensub(/([[:digit:].]*)(\(.*\))/, "\\2 \\1", "g")}' file

Я, хотя, установив разделитель полей (;), "мой обмен регулярными выражениями" будет успешным в каждом поле.Это была ошибка.

Вот пример отказа

;(:);7320000(n,d);(:)

желаемый результат -> ;(:);(n,d) 7320000;(:)

Мои вопросы (наконец-то): почему awkошибка при успешном завершении с файлом с одним столбцом.Какой лучший инструмент для решения этой проблемы?

  1. sed с очень длинным регулярным выражением?
  2. awk с очень длинным регулярным выражением?
  3. for loop?
  4. другие инструменты?

PS: я знаю, что не ясно.У меня 2 проблемы (английский язык, технические ограничения).К сожалению.

Ответы [ 3 ]

0 голосов
/ 15 декабря 2018

Это может сработать для вас (GNU sed):

sed -r 's/([0-9]+(\.[0-9]+)?)(\([^)]*\))/\3 \1/g' file

Найдите группу чисел (возможно, с десятичной запятой), за которой следует пара скобок, и переставьте их желаемым образом, глобально черезиз каждой строки.

0 голосов
/ 16 декабря 2018

Ваш "вопрос" слишком длинный, загроможденный и содержит слишком много отдельных вопросов, чтобы его разобрать, но вот как получить желаемый результат из ввода, предоставленного вами для любого sed:

$ sed 's/\([0-9][0-9.]*\)\(([^)]*)\)/\2 \1/g' file
...;field;(:);(n,d) 10000;(:);field;....
...;field;(b) 123.12;(a) 123;(:) 123.00;....
0 голосов
/ 15 декабря 2018

Что ж, при разборе простых разделенных файлов без каких-либо значений в кавычках, обычно на помощь приходит awk:

awk -vFS=';' -vOFS=';' '{
    for (i = 1; i < NF; i++) {
        split($i, t, "(")
        if (length(t[1]) != 0 && length(t[2]) != 0) {
            $i="("t[2]" "t[1]
        }
    }
    print
}' <<EOF
...;field;(:);10000(n,d);(:);field;....
...;field;123.12(b);123(a);123.00(:);....
EOF

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

  1. Сначала мы устанавливаем входной и выходной разделители как ;
  2. Итерируем по всем полям в строке for (i = 1; i < NF; i++)
  3. Мы разделяем строку на ( символ
  4. Если первое поле, разделенное на (, имеет ненулевую длину, а второе поле также имеет ненулевую длину
  5. Мы меняем местамидобавьте пробел для этого поля и добавьте пробел (мы также помним об удаленном ( в начале).
  6. А затем строка получит print ed.

Решениеиспользуя sed и xargs, но вам нужно заранее знать количество полей:

{
    sed 's/;/\n/g' |
    sed 's/\([^(]\{1,\}\)\((.*)\)/\2 \1/' |
    xargs -d '\n' -n7 -- printf "%s;%s;%s;%s;%s;%s;%s\n"
} <<EOF
...;field;(:);10000(n,d);(:);field;....
...;field;123.12(b);123(a);123.00(:);....
EOF
  1. Для каждого ; я делаю новую строку
  2. Для каждогоВ строке i я заменяю строку как минимум на символ перед ( и строку внутри ).
  3. Затем я объединяю 7 строк, используя ; в качестве разделителя с xargs и printf.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...