Изменение шаблонов с помощью SED

Один из способов сделать это с помощью редактора sed:

sed -e '
   s/,/\n/
   s/\(\n.*[[:blank:]]\)\([^,]*\),/ \2\1/
   P;D
' input.file

Рабочий:

  • Вырезать начальный элемент, разделенный запятой -, из 2-го поля.
  • Затем добавьте этот элемент в элемент первого поля, разделенный запятой -.
  • Напечатайте начальный элемент 1-го поля и удалите его после этого.
  • Повторяйте эту процедуру с тем, что осталось в пространстве шаблонов, пока оно не станет пустым.

Другой метод, использующий Perl,:

perl -lane '
   my($kref, $vref, %h) = map { [split /,/] } @F[0,1];
   @h{@$kref} = @$vref;
   print "$_  $h{$_}" for @$kref;
' input.file

Здесь показан другой способ:

perl -lpe 'print "$1 $3" while s/^([^,]*),(.*\h)([^,]*),/$2/' input.file

Работа:

  • Посмотрите на регулярное выражение таким образом:(Perl читает строку за раз из файла ), затем :
    • ^ ([^,]*)должен выбрать первый -элемент текущей строки, разделенный запятой -. Это хранится в переменной $1.
    • (. *\h)должен сохранить для следующей итерации цикла while промежуточное содержимое, начиная со второго элемента, разделенного запятой -первого поля, до начала второго элемента, разделенного запятой -второе поле. Это хранится в переменной $2.
    • ([^,]*)должен выбрать начальный элемент, разделенный запятой -, из второго поля текущей строки. Он сохраняется в переменной $3.
    • Теперь «$1 $3» выводится в STDOUT, а строка сокращается до $2. Цикл while теперь выполняет операцию снова и снова в этой отредактированной строке, которая составляет $2 от предыдущей строки,..... это повторяется до тех пор, пока s/// не завершится успешно. Неудача наступает, когда заканчиваются запятые. В этот момент то, что осталось в строке «c 5», выводится в STDOUT в соответствии с поведением Perl по умолчанию в режиме -p.
  • Удалить элементы, разделенные начальной запятой -из первого и второго полей.
  • Распечатать эти элементы, а также уменьшить текущую запись путем удаления.
  • Перебрать текущую запись, если в ней есть 2 запятые.
  • Последняя пара печатается автоматически -из-за опции -p в Perl.

perl -lane '
   my($kref, $vref) = map { [split /,/] } @F;
   print shift @$kref, " ", shift @$vref while @$kref && @$vref;
' input.file

Работа:

  • ключи хранятся в массиве @$kref, соответствующие значения — в @$vref. Обратите внимание, что здесь нет хэшей.
  • одновременно напечатать верхнюю часть массивов, а затем удалить верхнюю часть... полоскать, повторять, пока оба массива не пусты -.

Выход:

a 1
b 2
c 3
d 4
e 5
f 6
g 7
h 8
-1
05.05.2020, 07:59
2 ответа

Используйте группу захвата (...)для трехбуквенной комбинации, т. е. ([A-Z]{3})и используйте \1для ссылки на эту (первую группу )в замене.

Пример:

$ printf '%s\n' AGLU AASP ALYS AVAL | sed -E 's/A([A-Z]{3})/ \1/'
 GLU
 ASP
 LYS
 VAL
2
28.04.2021, 23:16

Да, sedдолжно работать -, если я понимаю, что вы на самом деле хотите сделать. Вот пример строки (, которая может быть именем файла ), содержащим букву A. Подстановки SED ниже заменят первое вхождение буквы Aстрокой _,``(нулевой -длины )и . соответственно.

$ SOMEFILE="AASP"  
$ echo $SOMEFILE
AASP
$ echo $SOMEFILE | sed "s/A/_/"
_ASP
$ echo $SOMEFILE | sed "s/A//"
ASP
$ echo $SOMEFILE | sed "s/A/ /"
 ASP
0
28.04.2021, 23:16

Теги

Похожие вопросы