使用 awk 重新格式化文本文件并切割为一个衬里
Reformatting text file using awk and cut as a one liner
数据:
CHR SNP BP A1 TEST NMISS BETA SE L95 U95 STAT P
1 chr1:1243:A:T 1243 T ADD 16283 -6.124 0.543 -1.431 0.3534 -1.123 0.14
期望的输出:
MarkerName P-Value
chr1:1243 0.14
实际文件是1.2G的行如上
我需要将文本的第 2 列去掉第 2 个冒号,然后将其粘贴到最后的第 12 列并给它一个新的 header。
我试过:
awk '{print , }' | cut -d: -f1-2
但这会删除冒号后的整行,我想保留“p”列
我将其输出到一个新文件,然后使用 awk 将其粘贴到 P-value 列,但想知道是否有 one-liner 方法来执行此操作?
非常感谢
编辑: 在这里添加一个解决方案,因为 OP 提到我的第一个解决方案不知何故不适用于 OP,但它工作正常对我来说,作为替代方案在这里添加这个。
awk '
BEGIN{
print "MarkerName P-Value"
}
FNR>1{
match(,/([^:]*:){2}/)
print OFS substr(,RSTART,RLENGTH-1),$NF
}
' Input_file
显示示例,请您尝试以下操作。 cut
不需要和awk
一起使用,awk
可以搞定一切。
awk -F' +|:' '
BEGIN{
print "MarkerName P-Value"
}
FNR>1{
print OFS ":",$NF
}
' Input_file
说明: 为以上添加详细说明。
awk -F' +|:' ' ##Starting awk program from here and setting field separator as spaces or colon for all lines.
BEGIN{ ##Starting BEGIN section of this program from here.
print "MarkerName P-Value" ##Printing headers here.
}
FNR>1{ ##Checking condition if line number is greater than 1 then do following.
print OFS ":",$NF ##Printing space(OFS) 2nd field colon 3rd field and last field as per OP request.
}
' Input_file ##Mentioning Input_file name here.
我的评论更容易理解:
$ awk '
BEGIN {
print "MarkerName P-Value" # output header
}
NR>1 { # skip the funky first record
split(,a,/:/) # split by :
printf "%s:%s %s\n",a[1],a[2], # printf allows easier output formating
}' file
输出:
MarkerName P-Value
chr1:1243 0.14
Sed 替代方案:
sed -En '1{s/^.*$/MarkerName\tP-Value/p};s/([[:digit:]]+[[:space:]]+)([[:alnum:]]+:[[:digit:]]+)(.*)([[:digit:]]+\.[[:digit:]]+$)/\t/p'
对于第一行,用整行替换 headers。然后,根据正则表达式将该行分成 4 部分,然后打印第 2 小节,然后是制表符,然后是第 4 小节。
$ awk -F'[: ]+' '{print (NR==1 ? "MarkerName P-Value" : ":"" "$NF)}' file
MarkerName P-Value
chr1:1243 0.14
数据:
CHR SNP BP A1 TEST NMISS BETA SE L95 U95 STAT P
1 chr1:1243:A:T 1243 T ADD 16283 -6.124 0.543 -1.431 0.3534 -1.123 0.14
期望的输出:
MarkerName P-Value
chr1:1243 0.14
实际文件是1.2G的行如上
我需要将文本的第 2 列去掉第 2 个冒号,然后将其粘贴到最后的第 12 列并给它一个新的 header。
我试过:
awk '{print , }' | cut -d: -f1-2
但这会删除冒号后的整行,我想保留“p”列
我将其输出到一个新文件,然后使用 awk 将其粘贴到 P-value 列,但想知道是否有 one-liner 方法来执行此操作?
非常感谢
编辑: 在这里添加一个解决方案,因为 OP 提到我的第一个解决方案不知何故不适用于 OP,但它工作正常对我来说,作为替代方案在这里添加这个。
awk '
BEGIN{
print "MarkerName P-Value"
}
FNR>1{
match(,/([^:]*:){2}/)
print OFS substr(,RSTART,RLENGTH-1),$NF
}
' Input_file
显示示例,请您尝试以下操作。 cut
不需要和awk
一起使用,awk
可以搞定一切。
awk -F' +|:' '
BEGIN{
print "MarkerName P-Value"
}
FNR>1{
print OFS ":",$NF
}
' Input_file
说明: 为以上添加详细说明。
awk -F' +|:' ' ##Starting awk program from here and setting field separator as spaces or colon for all lines.
BEGIN{ ##Starting BEGIN section of this program from here.
print "MarkerName P-Value" ##Printing headers here.
}
FNR>1{ ##Checking condition if line number is greater than 1 then do following.
print OFS ":",$NF ##Printing space(OFS) 2nd field colon 3rd field and last field as per OP request.
}
' Input_file ##Mentioning Input_file name here.
我的评论更容易理解:
$ awk '
BEGIN {
print "MarkerName P-Value" # output header
}
NR>1 { # skip the funky first record
split(,a,/:/) # split by :
printf "%s:%s %s\n",a[1],a[2], # printf allows easier output formating
}' file
输出:
MarkerName P-Value
chr1:1243 0.14
Sed 替代方案:
sed -En '1{s/^.*$/MarkerName\tP-Value/p};s/([[:digit:]]+[[:space:]]+)([[:alnum:]]+:[[:digit:]]+)(.*)([[:digit:]]+\.[[:digit:]]+$)/\t/p'
对于第一行,用整行替换 headers。然后,根据正则表达式将该行分成 4 部分,然后打印第 2 小节,然后是制表符,然后是第 4 小节。
$ awk -F'[: ]+' '{print (NR==1 ? "MarkerName P-Value" : ":"" "$NF)}' file
MarkerName P-Value
chr1:1243 0.14