Команда Sed для замены чисел между пробелами и: - PullRequest
2 голосов
/ 24 апреля 2019

У меня есть файл с записями, подобными приведенным ниже

FIRST 1: SECOND 2: THREE 4: FIVE 255: SIX 255

Я хочу удалить значения между пробелом и:

FIRST:SECOND:THREE:FIVE:SIX

с кодом

awk -F '[[:space:]]*,:*' '{$1=$1}1' OFS=, file

Ответы [ 3 ]

1 голос
/ 25 апреля 2019

пробовал на GNU AWK:

awk -F' [0-9]*(: *|$)' -vOFS=':' '{print $1,$2,$3,$4,$5}' file

примерял GNU SED:

sed -E 's/\s+[0-9]+(:|$)\s*/\1/g' file

Объяснение awk,
регулярное выражение , пробел, за которым следует [0-9]+ одно или несколько чисел, за которыми следует литерал :, за которым следует один или несколько пробелов: *, если все такие совпадают, то соберите все, кроме этого сопоставленного шаблона, т.е. FIRST, SECOND, ... и т. Д., Так как параметр -F определяет его как разделитель полей (FS) и $ 1, $ 2 .. и т. Д. Всегда остальное, чем FS. Но на выходе нужен красивый внешний вид, т.е. имеет FS, так что это будет :, и это будет определение переменной awk -vOFS = ':'

1 голос
/ 24 апреля 2019

Вы можете добавить [[:digit:]] также с конечной звездочкой и оставить только пробел сразу после OFS=:

$ awk -F '[[:space:]][[:digit:]]*' '{$1=$1}1' OFS= file
FIRST:SECOND:THREE:FIVE:SIX
0 голосов
/ 28 апреля 2019

Чтобы получить желаемый вывод в идиоматическом awk , мы делаем разделитель поля ввода (с -F), содержащий все, что мы хотим удалить (привязанный с :), и делаем разделитель выходного поля (OFS) на что мы хотим заменить. Загвоздка в том, что это не устранит пробел и цифры в конце строки, и для этого нам нужно сделать что-то большее. Реализация GNU awk позволит нам использовать регулярное выражение для разделителя входной записи (RS), но мы могли бы просто сделать sub() с жалобой POSIX awk как Что ж. Наконец, принудительный пересчет с помощью $1=$1 ... побочные эффекты для этого шаблона / оператора заключаются в том, что буфер будет пересчитан при замене FS / RS для нас, и что непустые строки будут выполнять действие по умолчанию - то есть печать.

gawk -F '[[:space:]]*[[:digit:]]*:[[:space:]]*' -v OFS=: -v RS='[[:space:]]*[[:digit:]]*\n' '$1=$1' file

Или:

awk -F '[[:space:]]*[[:digit:]]*:[[:space:]]*' -v OFS=: '{ sub(/[[:space:]]*[[:digit:]]*$/, “”) } $1=$1' file

A sed реализация забавна, но, вероятно, медленнее (потому что текущие версии awk имеют лучшие реализации регулярных выражений).

sed 's/[[:space:]]*[[:digit:]]*:[[:space:]]/:/g; s/[[:space:]]*[[:digit:]]*[[:space:]]*$//' file

Или, если классы символов POSIX недоступны ...

sed 's/[\t ]*[0-9]*:[\t ]/:/g; s/[\t ]*[0-9]*[\t ]*$//' file

Что-то говорит мне, что ваш «ПЕРВЫЙ, ВТОРОЙ, ТРЕТИЙ ...» может быть более сложным и содержать цифры ... в этом случае вы можете поэкспериментировать с заменой * на + для awk или \+ для sed .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...