我有一个包含以下内容的文件:
CHROM_POS
chr10_100009635
chr10_100187980
chr10_100229692
chr10_100267650
chr10_100269675
chr10_100279430
chr10_100285899
我想向该文件添加新内容,例如:
chrX-1, chrX
其中X代表上面的数字所以它应该是
chr10_100285898 chr10_100285899
答案1
Perl 解决方案:
perl -p -e 's;([^_]+)_(\d+);"$1_" . ($2 - 1) . " $1_$2";e'
该-p
标志循环所有行,-e
将脚本作为参数给出。捕获, (\d+) $2 e` 修饰符([^_]+)
之前的内容以替换启用表达式。_
$1
captures the digits into
, the
将您的输入文件作为参数或仅作为标准输入。
答案2
使用awk
:
awk -F _ 'NR > 1 { $0 = sprintf("%s_%d, %s_%d", $1, $2-1, $1, $2) }; 1' file
或者稍微短一些,
awk -F _ 'NR > 1 { $0 = sprintf("%s_%d, %s", $1, $2-1, $0) }; 1' file
这假设您希望保持第一行完整,并且希望在结果列之间使用逗号。sprintf()
如果不需要逗号,请从格式字符串中删除逗号。
该代码不对第一行执行任何操作,而是sprintf()
根据chrX_(N-1), chrX_N
模式重写所有其他行,这似乎正是您所要求的。
通过将数据视为两个_
分隔字段来挑选出原始行的位,即染色体名称和染色体上的基因组位置。因此,染色体名称被读入$1
,位置被读入$2
。
代码最后1
的awk
会导致数据(无论是否修改)被输出。
给定示例数据的输出:
CHROM_POS
chr10_100009634, chr10_100009635
chr10_100187979, chr10_100187980
chr10_100229691, chr10_100229692
chr10_100267649, chr10_100267650
chr10_100269674, chr10_100269675
chr10_100279429, chr10_100279430
chr10_100285898, chr10_100285899
答案3
基于awk的解决方案:
awk -F '_' -v OFS=, 'NR>1{ $0 = $1 FS $2-1 OFS $0 }1' file
结果:-
CHROM_POS
chr10_100009634,chr10_100009635
chr10_100187979,chr10_100187980
chr10_100229691,chr10_100229692
chr10_100267649,chr10_100267650
chr10_100269674,chr10_100269675
chr10_100279429,chr10_100279430
chr10_100285898,chr10_100285899
其他方法:
[perl]
perl -lsne '
print $.>1 ? s/(\d+)$/$1-1/re : (), $_;
' -- -,=, file
[Python3]
python3 -c 'import sys
with open(sys.argv[1]) as f:
for nr,_ in enumerate(f,1):
_ = _.rstrip("\n")
if nr > 1:
p = _.find("_") + 1
_ = _[:p] + f"{int(_[p:])-1}," + _
print(_)
' file
[GNU dc] RPN 计算器
< file \
sed 's/^/[/;1s/$/]/;1!s/_/&]/' |
dc -e "
[q]sq
[rdnrd1-n44anrnpc]sp
[?z0=q lpx z0=?]s?
?pc l?x
"
[GNU sed]
sed -Ee '1b
h
s/^[^_]*_//
s/$/\n9876543210/;tdecr
:decr
s/([^0])\n.*\1(.).*/\2/;tdone
s/([^0])(0+\n.*\1(.))/\3_\2/
:loop
s/_0(0*\n)/9_\1/
tloop
s/_.*//
:done
G
s/.*\n([^_]*_)/\1&/
y/\n/,/
' file