我有一个名为baitmap.txt的表。在$ 5中,不同的基因名称用“,”分隔。
baitmap.txt
1 831895 848168 218 RP11-54O7.1-001
1 848169 850618 219 RP11-54O7.2-001
1 850619 874081 220 SAMD11-011,SAMD11-003,SAMD11-010,SAMD11-001,SAMD11-004
1 889424 903640 223 NOC2L-001
1 903641 927394 224 C1orf170-001,C1orf170-201
1 927395 936954 225 HES4-002,HES4-001,HES4-004
1 943677 957199 228 RP11-54O7.11-001
1 1005127 1034268 234 RNF223-201
1 1049052 1062659 239 C1orf159-002,C1orf159-001,C1orf159-004,C1orf159-009,C1orf159-011,C1orf159-017,C1orf159-016,C1orf159-203,C1orf159-201,C1orf159-204,C1orf159-202
1 1096739 1107115 246 MIR200B-201
我想在$ 5中拆分名称,然后将新列分别合并到前面的4列中。所以它应该像这样:
1 831895 848168 218 RP11-54O7.1-001
1 848169 850618 219 RP11-54O7.2-001
1 850619 874081 220 SAMD11-011
1 850619 874081 220 SAMD11-003
1 850619 874081 220 SAMD11-010
1 850619 874081 220 SAMD11-001
1 850619 874081 220 SAMD11-004
1 889424 903640 223 NOC2L-001
1 903641 927394 224 C1orf170-001
1 903641 927394 224 C1orf170-201
答案 0 :(得分:5)
awk '{split($5, a, ","); $5=""; for( k in a) print $0, a[k]}' baitmap.txt
请注意,awk对数组进行哈希处理,以便置换顺序。如果那很重要,您可以这样做:
awk '{n = split($5, a, ","); $5=""; for(k=1; k<=n; k++) print $0, a[k]}' baitmap.txt
答案 1 :(得分:2)
使用普通bash:
while read -ra fields; do
# split the last field into the "values" array
IFS=, read -ra values <<< "${fields[-1]}"
for val in "${values[@]}"; do
fields[-1]=$val
echo "${fields[*]}"
done
done < baitmap.txt
这需要bash v4.3 +分配给fields[-1]
。要使用较旧的bash(例如,在Mac上为/ bin / bash),
while read -ra fields; do
len=${#fields[@]}
IFS=, read -ra values <<< "${fields[len-1]}"
for val in "${values[@]}"; do
fields[len-1]=$val
echo "${fields[*]}"
done
done < baitmap.txt
答案 2 :(得分:0)
我是在几行BAT中完成此操作的(仅限于Dos / Windows)
@echo off
for /F "tokens=1-5" %%a in (baitmap.txt) do (
for %%i in (%%e) do (
echo %%a %%b %%c %%d %%i
)
)
1 831895 848168 218 RP11-54O7.1-001
1 848169 850618 219 RP11-54O7.2-001
1 850619 874081 220 SAMD11-011
1 850619 874081 220 SAMD11-003
1 850619 874081 220 SAMD11-010
1 850619 874081 220 SAMD11-001
1 850619 874081 220 SAMD11-004
1 889424 903640 223 NOC2L-001
1 903641 927394 224 C1orf170-001
1 903641 927394 224 C1orf170-201
1 927395 936954 225 HES4-002
1 927395 936954 225 HES4-001
1 927395 936954 225 HES4-004
1 943677 957199 228 RP11-54O7.11-001
1 1005127 1034268 234 RNF223-201
1 1049052 1062659 239 C1orf159-002
1 1049052 1062659 239 C1orf159-001
1 1049052 1062659 239 C1orf159-004
1 1049052 1062659 239 C1orf159-009
1 1049052 1062659 239 C1orf159-011
1 1049052 1062659 239 C1orf159-017
1 1049052 1062659 239 C1orf159-016
1 1049052 1062659 239 C1orf159-203
1 1049052 1062659 239 C1orf159-201
1 1049052 1062659 239 C1orf159-204
1 1049052 1062659 239 C1orf159-202
1 1096739 1107115 246 MIR200B-201
答案 3 :(得分:0)
由于该问题最初被标记为C
,因此似乎应该这样做:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
static void
process_line(const char *line)
{
const char *b = line;
int p = 1;
for(int field = 0; *b; b++) {
if( p && !isspace(*b) && ++field == 5 ) {
break;
}
p = isspace(*b);
}
int len = b - line;
const char *s = b;
for( ; *b; b++ ) {
if( *b == ',' || *b == '\n' ) {
fwrite(line, 1, len, stdout);
fwrite(s, 1, b - s, stdout);
putchar('\n');
s = b + 1;
}
}
}
int
main(int argc, char *const argv[])
{
(void)argc;
(void)argv;
char *line = NULL;
size_t s;
while( getline(&line, &s, stdin) != -1 ) {
process_line(line);
}
free(line);
return 0;
}
答案 4 :(得分:0)
另一个bash变体
while read line; do
first="${line% *}"
last="${line##* }"
printf "$first ${last//,/\\n$first }\n"
done < baitmap.txt