我有多个*csv文件,我喜欢:
#sample,time,N
SPH-01-HG00186-1_R1_001,8.33386,93
SPH-01-HG00266-1_R1_001,7.41229,93
SPH-01-HG00274-1_R1_001,7.63903,93
SPH-01-HG00276-1_R1_001,7.94798,93
SPH-01-HG00403-1_R1_001,7.99299,93
SPH-01-HG00404-1_R1_001,8.38001,93
我试着把csv文件整理成:
#sample,time,N
HG00186,8.33386,93
HG00266,7.41229,93
HG00274,7.63903,93
HG00276,7.94798,93
HG00403,7.99299,93
HG00404,8.38001,93
我:
for i in $(ls *csv); do line=$(cat ${i} | grep -v "#" | cut -d'-' -f3); sed 's/*${line}*/${line}/g'; done
然而没有结果显示…有什么建议吗?谢谢。
使用awk
和用,
分割每一行的逻辑,然后用-
分割它们的第一个字段:
awk -v FS=',' -v OFS=',' 'NR > 1 { split($1,w,"-"); $1 = w[3] } 1' file.csv
使用sed
和不可能修改其他字段的健壮正则表达式:
sed -E 's/^([^,-]*-){2}([^,-]*)[^,]*/2/' file.csv
# or
sed -E 's/^(([^,-]*)-){3}[^,]*/2/' file.csv
使用下面的Perl一行代码:
perl -i -pe 's{.*?-.*?-(.*?)-.*?,}{$1,}' *.csv
Perl单行程序使用这些命令行标志:-e
:告诉Perl查找内联代码,而不是在文件中查找。-p
:每次循环输入一行,默认赋值给$_
。在每次循环迭代后添加print $_
。-i.bak
:就地编辑输入文件(覆盖输入文件)。在覆盖之前,保存原始文件的备份副本,在其名称后面附加扩展名.bak
(您可以省略.bak
,以避免创建任何备份文件)。
参见:perldoc perlrun
:如何执行Perl解释器:命令行开关perldoc perlre
: Perl正则表达式(regexes)perldoc perlre
: Perl正则表达式(regexes):量词;字符类和其他特殊转义;断言;捕获组perldoc perlrequick
: Perl正则表达式快速入门
可以使用
sed -E 's/^[^-]+-[0-9]+-([^-]+)[^,]+/1/' file > newfile
细节:
-E
-启用POSIX ERE正则表达式样式^[^-]+-[0-9]+-([^-]+)[^,]+
-搜索的正则表达式模式^
-起始字符串[^-]+
-一个或多个非连字符-
-连字符[0-9]+
-一个或多个数字-
-连字符([^-]+)
-组1:一个或多个非连字符[^,]+
-一个或多个非逗号字符
1
-将匹配项替换为组1值
查看在线演示:
#!/bin/bash
s='SPH-01-HG00186-1_R1_001,8.33386,93
SPH-01-HG00266-1_R1_001,7.41229,93
SPH-01-HG00274-1_R1_001,7.63903,93
SPH-01-HG00276-1_R1_001,7.94798,93
SPH-01-HG00403-1_R1_001,7.99299,93
SPH-01-HG00404-1_R1_001,8.38001,93'
sed -E 's/^[^-]+-[0-9]+-([^-]+)[^,]+/1/' <<< "$s"
输出:
HG00186,8.33386,93
HG00266,7.41229,93
HG00274,7.63903,93
HG00276,7.94798,93
HG00403,7.99299,93
HG00404,8.38001,93
您可以使用bash参数扩展来修改文本,而无需借助awk和sed等外部工具:
IFS=","
while read -r -a line; do
x="${line[0]%-*}"
x="${x##*-}"
printf "%s,%s,%sn" "$x" "${line[1]}" "${line[2]}"
done < input.txt
或者您可以使用简单的awk,就像其他人所做的那样。
awk '{print $3,$5,$6}' FS='[-,]' OFS=, < input.txt
如果您需要不惜任何代价使用cut
,那么我建议以下解决方案,让file.txt
内容为
#sample,time,N
SPH-01-HG00186-1_R1_001,8.33386,93
SPH-01-HG00266-1_R1_001,7.41229,93
SPH-01-HG00274-1_R1_001,7.63903,93
SPH-01-HG00276-1_R1_001,7.94798,93
SPH-01-HG00403-1_R1_001,7.99299,93
SPH-01-HG00404-1_R1_001,8.38001,93
然后
head -1 file.txt && tail -6 file.txt | tr '-' ',' | cut --delimiter=',' --fields=3,5,6
给输出
#sample,time,N
HG00186,8.33386,93
HG00266,7.41229,93
HG00274,7.63903,93
HG00276,7.94798,93
HG00403,7.99299,93
HG00404,8.38001,93
解释:输出第一行按原样使用head
,然后将最后6行填充到tr
中,使用,
替换-
,最后使用cut
和,
分隔符并指定所需字段。
{m,n,g}awk NF++ FS='^[^-]+-[^-]+-|-[^,]+' OFS=
|
#sample,time,N
HG00186,8.33386,93
HG00266,7.41229,93
HG00274,7.63903,93
HG00276,7.94798,93
HG00403,7.99299,93
HG00404,8.38001,93