在bash中按列名称删除列

时间:2014-06-09 10:19:22

标签: bash

我想按名称指定列(即102),找到此列的位置,然后使用cut -5,7-之类的内容删除指定的列。

这是我的文件标题(delim = "\t"):

#CHROM  POS 1   100 101 102 103 107 108

5 个答案:

答案 0 :(得分:1)

这个awk应该可以工作:

awk -F'\t' -v c="102" 'NR==1{for (i=1; i<=NF; i++) if ($i==c){p=i; break}; next} {print $p}' file

答案 1 :(得分:0)

在bash中使用for循环:

C=1; for i in $(head file -n 1) ; do if [ $i == "102" ] ; then break ; else C=$(( $C + 1 )) ; fi ; done ; echo $C

一个完整的脚本

C=1
for i in $(head in_file -n 1) ; do
    echo $i
    if [ $i == "102" ] ; then
        break ;
    else
        echo $C
        C=$(( $C + 1 ))
    fi
done
cut -f1-$(($C-1)),$(($C+1))- in_file

答案 2 :(得分:0)

尝试解决方案而不循环遍历列,我得到:

#!/bin/bash
pick="$1"
titles="pos 1 100 102 105"

tmp=" $titles "
tmp="${tmp%% $pick* }"
tmp=($tmp)

echo "column ${#tmp[@]}"

如果无法找到列名,则会错误地报告最后一列。

答案 3 :(得分:0)

这是一种可能的解决方案,没有限制只删除一列。它被写为bash函数,其中第一个参数是文件名,其余参数是要排除的列。

rmcol() {
  local file=$1
  shift
  cut -f$(head -n1 "$file" | tr \\t \\n | grep -vFxn "${@/#/-e}" |
          cut -d: -f1 | paste -sd,) "$file"
}

如果您要选择而不是排除指定列,请将-vFxn更改为-Fxn

这几乎肯定需要某种解释。函数的前两行只是从参数中删除文件名并存储它以供以后使用。然后cut命令将选择适当的列;列号用复杂的管道计算如下:

head -n1 "$file" |  # Take the first line of the file
tr \\t \\n       |  # Change all the tabs to newlines [ Note 1]
grep                # Select all lines (i.e. column names) which
     -v             #   don't match
       F            #   the literal string
        x           #   which is the complete line
         n          #   and include the line number in the output
     "${@/#/-e}" |  # Put -e at the beginning of each command line argument,
                    #   converting the arguments into grep pattern arguments (-e)
cut -d: -f1      |  # Select only the line number from that matches
paste -sd,          # Paste together all the line numbers, separated with commas.

答案 4 :(得分:0)

尝试使用该小型awk实用程序剪切特定的标头-https://github.com/rohitprajapati/toyeca-cutter

示例用法-

awk -f toyeca-cutter.awk -v c =“ col1,col2,col3,col4” my_file.csv