How can I split a word's letters, with each last four letters in a line?

Можно использовать несколько каналов ssh следующим образом:

docker save testi/myapp  | gzip  | pv | ssh ubuntu@bastion "cat | pv | ssh ubuntu@host \"docker load\" "

Эта команда загружает файл на хост-машину через бастион, и файл не сохраняется в бастионе машина.

2
08.08.2017, 13:26
4 ответа

Использование Perl (и использование только однобайтовых -символов):

perl -ne 'print scalar(reverse join " ", (reverse =~ /.{1,4}/g)), "\n"'
  • Внутренний reverseперевернет заданное слово (на самом деле, всю входную строку, независимо от того, что она содержит ).
  • Регулярное выражение разбивает перевернутое слово на фрагменты по четыре символа (последний фрагмент с начала исходного слова может содержать меньше символов ).
  • joinсоединит эти фрагменты в строку, но с пробелами в -между ними.
  • Внешний reverseпереворачивает объединенную строку.
  • scalarиспользуется, чтобы заставить внешний reverseработать в скалярном контексте.
  • printвыводит результат.

Приведенный ниже код делает то же самое, но устраняет scalar, "\n"и print, используя -p, -lи присваивая$_:

perl -lpe '$_ = reverse join " ", reverse =~ /.{1,4}/g'
1
27.01.2020, 21:58

С помощью sedвы можете сделать что-то вроде:

sed '
  G
  :1
      s/\([[:alpha:]]\)\([[:alpha:]]\{4\}\)\(\n\)/\1\3 \2/
  t1
  s/\n//
'

Мы используем символ новой строки в качестве бегущего маркера. (Новая строка — это единственный символ, который не будет появляться внутри начального пространства шаблона ). Мы добавляем его в конце изначально. Затем, пока мы находим ABCDE<marker>(, где ABCDE — 5 буквенных символов, вы можете заменить [[:space:]]на [^[:blank:]], если хотите рассматривать слова как последовательности не -пробелов, а не последовательности букв ), мы заменяем его на A<marker> BCDEи зацикливаем. И удаляем маркер в конце.

Таким образом,мы уверены, что обработаем только то слово, которое находится только в конце строки.

Если бы вы хотели разбить таким образом каждое слово, а не только последнее слово, это было бы проще:

sed -e :1 -e 's/\(.*[[:alpha:]]\)\([[:alpha:]]\{4\}\)/\1 \2/;t1'

Если ваш ввод содержит разложенные символы (, как в выводе printf 'abcd\u00e9e\u0301f\n':abcdééf), вы можете сделать:

perl -Mopen=locale -lpe 'while(s/.*(?=\w)\X\K(?:(?=\w)\X){4}/ $&/){}'
1
27.01.2020, 21:58

awk решение:

awk '{ c=0; for(i=length($2);i>0;i-=4) {a[++c]=(i-4>0)? substr($2,i-4+1,4) : substr($2,1,i)} 
    $2=""; for(i=length(a);i>0;i--) $2=$2 FS a[i] }1' file

Выход:

1.  pla cing
2.  back tick
3.  pa ragr aphs
1
27.01.2020, 21:58

С Perlиспользуя lookaroundsмы могли бы выполнить операцию как:

perl -pe 's/(?<=\w)(?=(?:\w{4})+$)/ /g'

Что переводится как :, когда мы стоим на позиции, слева от нас находится буквенно-цифровая цифра, а справа от нас по крайней мере 4 alnum или кратные им числа. прямо до конца строки. Всякий раз, когда такая позиция существует, пространство размещены там. Это глобально влияет на запрошенное изменение.

Мы могли бы использовать bashдля этого:

#!/bin/bash

# symbolic constants
NL=$'\012'; # newline
SP=$'\040'; # space

# elementary regexes
alnum='[0-9a-zA-Z]'; # a single alphanumeric
alnums4=$(csh -c 'repeat 4 echo -n "$1"' "$alnum"); # 4 consecutive alnums

# main processing
while IFS= read -r line res; do
   while c4=$(expr "$SP$line$NL" : ".*$alnum\($alnums4\)$NL")
   do
      res=${c4}${res:+"$SP"}${res-} line=${line%????}
   done
   printf '%s %s\n' "$line" "$res"
done

Использование редактора GNU sed:

sed -Ee '
   s/\S+/\n&\n/2; # enclose the 2nd field with markers

   # a do-while loop to progessively move the right marker to the left,
   # consuming 4 alnums in each iteration. Looping stops when 4 alnums+
   # 1 alnum at the boundary remains.
   :loop
      s/(\n[[:alnum:]].*)([[:alnum:]]{4})\n/\1\n \2/
   tloop

   # clear out the markers when done
   s/\n//g
'
1
27.01.2020, 21:58

Теги

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