Shell POSIX:abcdef至ab bc cd de ef
使用POSIXShell POSIX:abcdef至ab bc cd de ef,shell,awk,sed,posix,Shell,Awk,Sed,Posix,使用POSIXsed或awk,我想复制每一对相邻字符中的每一个字符,并在新行中列出每一对新形成的字符 example.txt: abcd 10001. 预期结果: ab bc cd d 1 10 00 00 01 1. 到目前为止,这就是我所拥有的(注意省略“-posix”if on macOS)。由于某些原因,在\2之前添加文字换行符不会产生预期的结果。删除第一个组并使用\1具有相同的效果。我错过了什么 sed --posix -E -e 's/(.)(.)/&\2\ /g'
sed
或awk
,我想复制每一对相邻字符中的每一个字符,并在新行中列出每一对新形成的字符
example.txt:
abcd 10001.
预期结果:
ab
bc
cd
d
1
10
00
00
01
1.
到目前为止,这就是我所拥有的(注意省略“-posix”if on macOS)。由于某些原因,在\2
之前添加文字换行符
不会产生预期的结果。删除第一个组并使用\1
具有相同的效果。我错过了什么
sed --posix -E -e 's/(.)(.)/&\2\
/g' example.txt
abb
cdd
100
000
1..
你可以用
sed --posix -e 's/./&\
&/g' example.txt | sed '1d;$d'
第一个sed
命令查找字符串中的每个字符并替换为相同的字符,然后换行,然后再次替换相同的字符。由于它替换了第一个和最后一个字符,因此必须删除第一个和最后一个结果行,这是通过sed'1d实现的$d'
如果
sed
支持lookarounds,则可以使用(?!^)。(?!$)
(任何字符,但不在字符串的开头或结尾)和最后一个sed
命令,但这在sed
中是不可能的。您可以在perl
中使用它,perl-pe的/(?!^)。(?!$)/$&\n$&/g'example.txt
(请参见,RHS中的$&
与sed
中的占位符相同,即整个匹配值)。使用GNUawk
您可以尝试以下内容吗。使用显示的样本进行书写和测试,并在链接中进行测试
awk'
开始{
FS=“”
}
{
对于(i=1;i尝试:
$echo“abcd 10001.”awk'{for(i=1;i使用相同的例程,可以在bash
本身中完成:
s='abcd 10001.'
for((i=0; i<${#s}-1; i++)); do echo "${s:i:2}"; done
为了好玩,一个单一的sed
由3个替换组成:
$ echo "abcd 10001." | sed 's/./&&/g;s/\(^.\|.$\)//g;s/../&\n/g'
第一部分复制所有字符,第二部分删除第一个和最后一个字符,第三部分在每个字符对后添加换行符
如果您想与POSIX兼容,必须执行以下操作:
$ echo "abcd 10001." | sed -e 's/./&&/g' -e 's/^.//g' -e 's/.$//g' -e 's/../&\n/g'
这里我们不得不添加一个额外的表达式,因为表达式\(^.\\\.$)
是一个ERE,posix sed只接受BREposix没有指定进程替换。posix要求只针对awk
和sed
指定,所以下一个解决方案可能是可以接受的:
paste -d '\0' <(echo; fold -w1 example.txt) <(fold -w1 example.txt) | grep ..
这可能适用于您(GNU-sed):
将前两个字符替换为前两个字符,换行符和第二个字符
打印第一行如果它是两个字符长,删除第一行并重复
另一种更冗长的选择:
sed -E ':a;s/^(([^\n]{2}\n)*[^\n])([^\n])([^\n])/\1\3\n\3\4/;ta' file
或者,在没有硬编码新行的情况下:
sed -E '/.../{G;s/^(.(.))(.*)(.)/\1\4\2\3/;P;D}' file
最后:
sed 's/./&\n&/g;s/^..\|..$/g' file
同时拥有--posix
(仅GNU选项)是没有意义的和-E
选项,因为-E
在GNU-sed和OSX/BSD-sed中启用了ERE,但POSIX不支持ERE。另外,也不要假设如果使用-POSIX
运行脚本,它只使用POSIX指定的语法。这意味着非POSIX扩展被禁用,但它可能仍然依赖于行为r这根本不是POSIX定义的,因此它在其他POSIX sed中也不起作用。基本上,如果你在一行输入或输出上做的事情超过了s/old/new/g,那么你可能使用的是非可移植的构造。我不知道与sed相比,awk的可移植性有多大。我无法想象为什么有人会投反对票,因为这不是他是一个健壮的、可移植的解决方案,可以在任何shell中使用任何awk在所有UNIX系统上进行任何输入。无需另一个sed'1d;$d'
。您可以“点它”&g;s/^../;s/.$/'
@KamilCuk我以为你不能用;
在FreeBSD-sed中链接sed命令。是的,但我认为没有必要争论什么更好,sed's/../../../'f
,sed-e's/../'-e's/../../'f
或sed's/../'f/../'f;sed's/../../'f,它完全有效e相同。只是一个细节,可能是使用echo-n…
与OP case兼容,不让新行由sed获取和管理/输出?(awk没有问题)@bruno在Posix中,没有选项-n
粘贴-d“”
是一个GNUism。对于同一个函数,POSIX将是粘贴-d'\0'
。然后需要删除第一行,并使用|sed-e'1d;$d'
获得OPs示例。尽管很有创意!@dawg我编辑了我的答案(添加了\0)。我通过用两个字符对行进行grepping来删除第一行/最后一行
while read -n1 ch; do
printf "%s\n%s" "${ch}" "${ch}"
done < example.txt | grep ..
sed 's/./&&/g;s/.//' example.txt | grep -o ..
sed 's/.\(.\)/&\n\1/;/../P;D' file
sed -E ':a;s/^(([^\n]{2}\n)*[^\n])([^\n])([^\n])/\1\3\n\3\4/;ta' file
sed -E '/.../{G;s/^(.(.))(.*)(.)/\1\4\2\3/;P;D}' file
sed 's/./&\n&/g;s/^..\|..$/g' file