Shell POSIX:abcdef至ab bc cd de ef

Shell 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'

使用POSIX
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
中的
占位符相同,即整个匹配值)。

使用GNU
awk
您可以尝试以下内容吗。使用显示的样本进行书写和测试,并在链接中进行测试

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只接受BRE

posix没有指定进程替换。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