我有这样的情况:
my data
:
ID01 120120101
ID02 101010101
ID03 210210210
ID04 505052120
我想要这些数据:output
ID01 1 2 0 1 2 0 1 0 1
ID02 1 0 1 0 1 0 1 0 1
ID03 2 1 0 2 1 0 2 1 0
ID04 5 0 5 0 5 2 1 2 0
所以,我想分隔第二列中出现的所有数字(我的数据),但第一根柱必须保持完整。
为此,我尝试创建两个文件:一个具有 ID ($1-file1),另一个具有我想要用空格分隔的序列 (file2)。我尝试后:
sed -i -- 's//\t/g' file2
但我收到以下错误:
sed: -e expression #1, char 0: no previous regular expression
我该如何解决这个问题?
答案1
怎么样
perl -alne 'print join " ", $F[0], split("", $F[1])' data
ID01 1 2 0 1 2 0 1 0 1
ID02 1 0 1 0 1 0 1 0 1
ID03 2 1 0 2 1 0 2 1 0
ID04 5 0 5 0 5 2 1 2 0
如果您想要(完全)制表符分隔的输出,请更改为
perl -alne 'print join "\t", $F[0], split("", $F[1])' data
或者如果您想在ID
第二个字段的数字后面保留一个制表符,但用空格分隔,
perl -alne 'print join "\t", $F[0], join " ", split("", $F[1])' data
答案2
在 中sed
,空正则表达式意味着重用前一个正则表达式,在本例中您没有。如果您将列分开,您可以执行以下操作:
sed 's/./& /g' file2
(匹配任何字符,然后替换回我们与 匹配的任何字符&
,并添加空格。)
但仅更改第二列更容易awk
:
awk '{gsub(/./, "& ", $2)} 1' data
gsub
与 sed 中的几乎相同s///g
。据我测试,awk
确实支持空正则表达式,但这会增加一个额外的空格,因为它也在第一个数字之前匹配。 (嗯,上面还在末尾添加了一个额外的空格。)
答案3
它并不漂亮,但很有效
cat my_data | sed -e 's/./ &/g' -e 's/^ \(.\) \(.\) \(.\) \(.\) /\1\2\3\4/'
第一个表达式在所有字母之前放置一个空格。接下来删除第一部分中的空格。
您还可以编写脚本:
#! /bin/bash
while read ID NUMBERS; do
echo $ID$(echo $NUMBERS | sed -e 's/./ &/g')
done
然后运行
cat my_data | ./my_script
答案4
当您无法使用s
带有标志的命令时,一种方法是在带有该命令的循环中g
使用该命令(以后续条件为条件的跳转)。s
t
s
这里:
sed -e :1 -e 's/\([^ ]\)\([^ ]\{1,\}\)$/\1 \2/;t1'
即用该非空格、一个空格和该非空格序列替换行末尾的一个非空格,后跟一系列 1 个或多个非空格,然后重复,直到无法替换为止。所以对于每一行,它都是这样的(这里是第一行):
ID01 120120101
-> ID01 1 20120101
-> ID01 1 2 0120101
-> ID01 1 2 0 120101
-> ID01 1 2 0 1 20101
-> ID01 1 2 0 1 2 0101
-> ID01 1 2 0 1 2 0 101
-> ID01 1 2 0 1 2 0 1 01
-> ID01 1 2 0 1 2 0 1 0 1
at this point the "s" command fails, so "t1" doesn't branch
和perl
:
perl -pe 's/\S+$/join " ", split "", $&/e'