sed打印第N个字符

时间:2018-01-29 07:41:15

标签: string bash shell sed

我有一个长度为5个字符的字符串列表。将每行的第一,第三和第五个字符(包括空格)转换为单个字符串的最佳方法是什么?

输入:

[Unit]
Description=Advanced key-value store
After=network.target
Documentation=http://redis.io/documentation, man:redis-server(1)

[Service]
Type=forking
ExecStart=/usr/bin/redis-server /etc/redis/redis.conf
ExecStop=/bin/kill -s TERM $MAINPID
PIDFile=/var/run/redis/redis-server.pid
TimeoutStopSec=0
Restart=always
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=2755

UMask=007
PrivateTmp=yes
LimitNOFILE=65535
PrivateDevices=yes
ProtectHome=yes
#Modified 20180129 to avoid issue to start redis
#redis-server.service: Failed at step NAMESPACE spawning /usr/bin/redis-server: Stale file handle
#ReadOnlyDirectories=/
ReadWriteDirectories=-/var/lib/redis
ReadWriteDirectories=-/var/log/redis
ReadWriteDirectories=-/var/run/redis

NoNewPrivileges=true
CapabilityBoundingSet=CAP_SETGID CAP_SETUID CAP_SYS_RESOURCE
MemoryDenyWriteExecute=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectControlGroups=true
RestrictRealtime=true
RestrictNamespaces=true
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX

# redis-server can write to its own config file when in cluster mode so we
# permit writing there by default. If you are not using this feature, it is
# recommended that you replace the following lines with "ProtectSystem=full".
ProtectSystem=true
ReadWriteDirectories=-/etc/redis

[Install]
WantedBy=multi-user.target
Alias=redis.service

输出:

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

我使用sed捕获组取得了一些成功,但忽略了尾随空格。

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

编辑:澄清我也需要包含空格,字符串包含一个点

5 个答案:

答案 0 :(得分:4)

这是一个使用GNU awk并清空public class ClasssATest { @Test public void someTest() { String input = "a string"; ExternalObject externalObject = Mockito.mock(ExternalObject.class); Mockito.when(externalObject.parseString(eq(input))).thenReturn(externalObject); ClassA sut = new ClassA(externalObject, input); ... } }

FS

答案 1 :(得分:4)

使用 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 :(得分:4)

使用awk awk内部变量的另一个不错的FIELDWITHS解决方案:

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,...

答案 3 :(得分:3)

我不知道使用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 - paste files without delimiter-d'\0'由POSIX定义,适用于任何版本的paste

答案 4 :(得分:2)

这可能适合你(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行和第1行之后添加换行符。第五个字符。在所有后续行中插入附加的行1st,3rd&amp;第5个字符。

N.B。输出请求交换最后两行,因此第3和第5个字符也被交换。