Используйте sed, чтобы заменить все вхождения строк, начинающихся с 'xy' и длиной 5 или более - PullRequest
0 голосов
/ 26 июня 2018

Я использую AIX 6.1

У меня есть файл, который содержит строки / слова, начинающиеся с некоторых определенных символов, скажем, 'xy' или 'Xy' или 'Xy' или 'XY' (без учета регистра), и мне нужно замаскировать все слово / строку звездочками '*', если слово больше, чем, скажем, 5 символов.

например. Мне нужна команда sed, которая при запуске против файла, содержащего строку ниже ...

This is a test line  xy12345  xy12  Xy123 Xy11111 which I need to replace specific strings

должен дать ниже как вывод

This is a test line xy12 which I need to replace specific strings

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

Я пытался использовать \ <и>, а также \ b для идентификации слова.

sed 's/\<xy\(.*\)\>/******/g' result2.csv
sed 's/\bxy\(.*\)\b******/g' result2.csv

Ответы [ 5 ]

0 голосов
/ 27 июня 2018

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

sed -r ':a;/\bxy\S{5,}\b/I!b;s//\n&\n/;h;s/[^\n]/*/g;H;g;s/\n.*\n(.*)\n.*\n(.*)\n.*/\2\1/;ta' file

Если текущая строка не содержит строку, начинающуюся с xy без учета регистра и 5 или более следующих символов, то никакой работы не требуется.

В противном случае:

  1. Окружить строку новыми строками
  2. Копирование пространства образца (PS) в пространство удержания (HS)
  3. Заменить все символы, кроме символов новой строки, на * s
  4. Добавить PS к ГС
  5. Заменить PS на HS
  6. Поменять строки между символами новой строки, сохранив остаток первой строки
  7. Повтор
0 голосов
/ 26 июня 2018

Простая версия POSIX awk:

awk '{for(i=1;i<=NF;++i) if ($i ~ /^[xX][yY]/ && length($i)>=5) gsub(/./,"*",$i)}1'

Это, однако, не сохраняет интервал нетронутым (несколько пробелов конвертируются в один), следующее делает:

awk 'BEGIN{RS=ORS=" "}(/^[xX][yY]/ && length($i)>=5){gsub(/./,"*")}1'
0 голосов
/ 26 июня 2018

с седом для умственных упражнений

sed -E '
  s/(^|[[:blank:]])([xyXY])([xyXY].{2}[^[:space:]]*)([^[:space:]])/\1@\3@/g
  :A
  s/(@[^@[:blank:]]*)[^@[:blank:]](@[@]*)/\1@\2/g
  tA
  s/@/*/g'

Это не должно иметь @ в тексте.

0 голосов
/ 26 июня 2018

Вы можете использовать awk:

s='This is a test line  xy12345  xy12  Xy123 Xy11111 which I need to replace specific strings xy123 xy1234 xy12345 xy123456 xy1234567'
echo "$s" | awk 'BEGIN {
    ORS=RS=" "
} 
{ 
    for(i=1;i<=NF;i++) {
        if(length($i) >= 5 && $i~/^[Xx][Yy][a-zA-Z0-9]+$/) 
            gsub(/./,"*", $i);
            print $i;
    } 
}'

Один вкладыш:

awk 'BEGIN {ORS=RS=" "} { for(i=1;i<=NF;i++) {if(length($i) >= 5 && $i~/^[Xx][Yy][a-zA-Z0-9]+$/) gsub(/./,"*", $i); print $i; } }'
# => This is a test line ******* xy12 ***** ******* which I need to replace specific strings ***** ****** ******* ******** *********

См. онлайн демо .

Детали

  • BEGIN {ORS=RS=" "} - начало awk: установить разделитель выходной записи равным разделителю записи пробела
  • { for(i=1;i<=NF;i++) {if(length($i) >= 5 && $i~/^xy[a-zA-Z0-9]+$/) gsub(/./,"*", $i); print $i; } } - выполнить итерацию по каждому полю (с for(i=1;i<=NF;i++)), и если длина текущего поля ($i) равна или больше 5 (length($i) >= 5) и соответствует Xy и (* 1026) *) 1 или более буквенно-цифровых символов ($i~/^[Xx][Yy][a-zA-Z0-9]+$/), затем замените каждый символ на *gsub(/./,"*", $i)) и напечатайте текущее значение поля.
0 голосов
/ 26 июня 2018

Вы можете попробовать с awk:

echo 'This is a test line  xy12345  xy12  Xy123 Xy11111 which I need to replace specific strings' | awk 'BEGIN{RS=ORS=" "} !(/^[xX][yY]/ && length($0)>=5)'

Разделитель записей awk установлен на пробел, чтобы иметь возможность получить длину каждого слова.

Это работает с GNUawk в режимах --posix и --traditional.

...