Исключение правильных строк

У меня есть шаблон регулярного выражения и замены, которые оба были протестированы в Notepad ++ на моих входных данных и работают правильно. Однако, когда я помещаю их в выражение sed, ничего не получается.

Вот команда sed:

 # SEARCH = ([a-zA-Z0-9.]+) [0-9] (.*)
 # REPLACE = \2 (\1)

 sed -e 's/\([a-zA-Z0-9.]+\) [0-9] \(.*\)/\2 \(\1\)/g'

Вот выборка данных:

jdoe 1 Doe, John
jad 1 Doe, Jane
smith 2 Smith, Jon

и желаемый результат:

Doe, John  (jdoe)
Doe, Jane  (jad)
Smith, Jon (smith)

Я попытался удалить и добавить escapes к различным символам в выражении sed, но либо не получил ничего согласованного или что-то вроде строк:

sed: -e expression #1, char 42: invalid reference \2 on `s' command RHS

Как я могу получить это экранированное правильно?

Ответ 1

Мне обычно проще использовать ключ -r, так как это означает, что экранирование аналогично экрану большинства других языков:

sed -r 's/([a-zA-Z0-9.]+) [0-9] (.*)/\2 (\1)/g' file1.txt

Ответ 2

Несколько предупреждений и дополнений к тому, что уже сказали все остальные:

Я бы рекомендовал переписать выражение как

's/\([a-zA-Z0-9.]\{1,\}\) [0-9] \(.*\)/\2 (\1)/g'

который должен делать именно то, что вы хотите в любом POSIX-совместимом sed. Если вы действительно заботитесь о таких вещах, подумайте об определении переменной среды POSIXLY_CORRECT.

Ответ 3

Знак плюса должен быть экранирован, если не используется переключатель -r.

Ответ 4

Использование awk намного проще...:

cat test.txt | awk '{ print $3 " " $4 " " "("$1")" }'

Вывод:

Doe, John (jdoe)
Doe, Jane (jad)
Smith, Jon (smith)

Смотрите man awk 1

Ответ 5

$ sed -e 's/\([a-zA-Z0-9.].*\) [0-9] \(.*\)/\2 \(\1\)/g' file
Doe, John (jdoe)
Doe, Jane (jad)
Smith, Jon (smith)