sed print N-й символ

У меня есть список строк длиной 5 символов. Каков наилучший способ преобразования первого, третьего и пятого символов (включая пробел) каждой строки в отдельные строки?

Входные данные:

c   c
8   8
4   4
3   3
1   1
4   4
9   9
8 | c
  > 4
0   0
e | 5
6 | a
3   3
9 | c
b <  
1   1
b | 0
d <  
4   4
5 | 7
c   c
  > 3
.   .
1 | c
o   o

Выход:

c8431498 0e639b1bd45c .1o
c843149c405a3c 10 47c3.co
       |> || |< |  | > |

У меня был некоторый успех с использованием группы захвата sed, но он игнорирует конечные пробелы.

sed -e "s/^.*\(.\)$/\1/"

Изменение: Уточнено, что мне нужно также пространство, а строка содержит точку

Ответ 1

используя GNU awk:

awk 'BEGIN{FS="";a="";b="";c="";}{a=a$1; b=b$3; c=c$5;}END{print a ORS c ORS b}' filename

выход:

c8431498 0e639b1bd45c 
c843149c405a3c 10 47c3
       |> || |< |< | >

Ответ 2

Здесь используется GNU awk и пустой FS:

$ awk -F "" '{for(i=1;i<=5;i++)a[i]=a[i] ($i==""?" ":$i)}END{print a[1] ORS a[5] ORS a[3]}' file
c8431498 0e639b1bd45c 
c843149c405a3c 10 47c3
       |> || |< |< | >

Ответ 3

Еще одно приятное awk решение, использующее внутреннюю переменную FIELDWITHS awk:

FIELDWIDTHS A  whitespace  separated  list  of field widths.  When set,
            gawk parses the input into fields of fixed  width,  instead
            of  using the value of the FS variable as the field separa-
            tor.  See Fields, above.

Пример:

$ awk -v FIELDWIDTHS="1 1 1 1 1" '{b1=b1$1;b3=b3$3;b5=b5$5}END{print b1;print b5;print b3}' to_horizontal.txt
c8431498 0e639b1bd45c 
c843149c405a3c 10 47c3
       |> || |< |< | >

вы можете использовать FIELDWIDTHS вместо классического FS для определения столбцов фиксированного размера, которые будут после манипулирования и доступа, как обычно, с помощью $1, $2, $3 ,...

Ответ 4

Я не знаю о том, как использовать sed для решения этой проблемы, кажется очень сложным, имея дело с вертикальными столбцами... так что здесь решение, использующее размятие cut/paste

$ # paste -s will convert all input lines into single line
$ # \0 delimiter means combine the lines with no character at all in between them
$ cut -c1 ip.txt | paste -sd'\0'
c8431498 0e639b1bd45c .1o
$ cut -c5 ip.txt | paste -sd'\0'
c843149c405a3c 10 47c3.co
$ cut -c3 ip.txt | paste -sd'\0'
       |> || |< |< | > | 

объединение результатов:

$ (cut -c1 ip.txt | paste -sd'\0'; cut -c5 ip.txt | paste -sd'\0'; cut -c3 ip.txt | paste -sd'\0') > f1
$ cat f1
c8431498 0e639b1bd45c .1o
c843149c405a3c 10 47c3.co
       |> || |< |< | > | 

$ # or use shell looping
$ for i in 1 5 3; do cut -c"$i" ip.txt | paste -sd'\0'; done
c8431498 0e639b1bd45c .1o
c843149c405a3c 10 47c3.co
       |> || |< |< | > | 

как unix.stackexchange - вставлять файлы без разделителя, -d'\0' определяется POSIX и должен работать с любой версией paste

Ответ 5

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

sed -r '1s/^(.).(.).(.)$/\1\n\3\n\2/;:a;N;s/(\n.*)(\n.*)\n(.).(.).(.)/\3\1\5\2\4/;ta' file

В первой строке добавляются символы новой строки после 1-го, 3-го и 5-го символов. На всех последующих строках вставьте прилагаемые строки 1-го, 3-го и 5-го символов.

NB выход запрашивает, что последние две строки меняются местами, поэтому третий и пятый символы также заменяются.