在bash中按列名剪切列

在bash中按列名剪切列,bash,Bash,我想按名称指定一列,即102,找到该列的位置,然后使用类似于cut-5,7的东西,在找到的位置删除指定的列 这是我的文件头delim=\t: 此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 在bash中使用for循环: C=1; for i in $(head file -n 1) ; do if [ $i ==

我想按名称指定一列,即102,找到该列的位置,然后使用类似于cut-5,7的东西,在找到的位置删除指定的列

这是我的文件头delim=\t:

此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
在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

在不循环列的情况下尝试解决方案,我得到:

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

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

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

如果找不到列名,它会错误地报告最后一列。

这里有一个可能的解决方案,没有只删除一列的限制。它作为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

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

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.

尝试此小awk实用程序来切割特定的标题-

示例用法-


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

OP想要删除列而不是打印它。如果看不到预期的输出,很难理解需求。cut-d'-f1命令通常只打印单列。这一行代码对我很有帮助,它只想按名称提取字段。也许是其他人要求解决这个不同的问题。我认为$I==102应该是$I=102给我一个这样的错误:正确,这是POSIX。使用BASH,你可以简单地做C++而不是C= $$C+1,甚至。回音$C++作为一个单独的操作。有一个简单的方法来做这一个以上的列吗?用BASH 4。x,是的,有这样一个简单的方式-你可以创建一个关联的列名数组到位置。为什么不要求剪切来补充你的选择当你想删除列,而不是保留它们?至少在Gnu切割的情况下。我认为BSD cut没有这个选择。但移除v非常容易:-
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.