取文本文件中的第n列



我有一个文本文件:

1 Q0 1657 1 19.6117 Exp
1 Q0 1410 2 18.8302 Exp
2 Q0 3078 1 18.6695 Exp
2 Q0 2434 2 14.0508 Exp
2 Q0 3129 3 13.5495 Exp

我想取每一行的第二个和第四个单词,像这样:

1657 19.6117
1410 18.8302
3078 18.6695
2434 14.0508
3129 13.5495

我使用这个代码:

 nol=$(cat "/path/of/my/text" | wc -l)
 x=1
 while  [ $x -le "$nol" ]
 do
     line=($(sed -n "$x"p /path/of/my/text)
     echo ""${line[1]}" "${line[3]}""  >> out.txt
     x=$(( $x + 1 ))
 done

它可以工作,但是它非常复杂,并且需要很长时间来处理长文本文件。

有更简单的方法吗?

iirc:

cat filename.txt | awk '{ print $2 $4 }'

或者,如注释中提到的:

awk '{ print $2 $4 }' filename.txt

您可以使用cut命令:

cut -d' ' -f3,5 < datafile.txt

打印

1657 19.6117
1410 18.8302
3078 18.6695
2434 14.0508
3129 13.5495

  • -d' ' -平均值,使用space作为分隔符
  • -f3,5 -取并打印第3和第5列

cut快得多对于大文件作为一个纯shell解决方案。如果文件用多个空格分隔,可以先删除它们,如:

sed 's/[t ][t ]*/ /g' < datafile.txt | cut -d' ' -f3,5

(gnu) sed将用单个space替换任何tabspace字符。

对于一个变量-这里也有一个perl解决方案:

perl -lanE 'say "$F[2] $F[4]"' < datafile.txt

为了完整:

while read -r _ _ one _ two _; do
    echo "$one $two"
done < file.txt

也可以使用任意变量(如junk)代替_。关键是要提取列。

演示:

$ while read -r _ _ one _ two _; do echo "$one $two"; done < /tmp/file.txt
1657 19.6117
1410 18.8302
3078 18.6695
2434 14.0508
3129 13.5495

还有一个简单的变体

$ while read line
  do
      set $line          # assigns words in line to positional parameters
      echo "$3 $5"
  done < file

如果你的文件包含n行,那么你的脚本必须读取文件n次;因此,如果你将文件的长度增加一倍,你的脚本所做的工作量就会增加四倍—几乎所有的工作都被简单地抛弃了,因为您所要做的就是按顺序遍历行。

相反,遍历文件行的最佳方法是使用while循环,并使用内置的read条件命令:

while IFS= read -r line ; do
    # $line is a single line of the file, as a single string
    : ... commands that use $line ...
done < input_file.txt

在您的例子中,由于您想将该行分割成一个数组,并且read内置实际上对填充数组变量有特殊的支持,这正是您想要的,您可以这样写:

while read -r -a line ; do
    echo ""${line[1]}" "${line[3]}"" >> out.txt
done < /path/of/my/text

或者更好:

while read -r -a line ; do
    echo "${line[1]} ${line[3]}"
done < /path/of/my/text > out.txt

然而,对于你正在做的事情,你可以使用cut实用程序:

cut -d' ' -f2,4 < /path/of/my/text > out.txt

(或awk,如Tom van der Woerdt所建议的,或perl,甚至sed)。

如果您使用的是结构化数据,那么这还有一个额外的好处,即不需要调用额外的shell进程来运行tr和/或cut或其他东西. ...

(当然,您需要使用条件和合理的替代来防止错误的输入。)

...
while read line ; 
do 
    lineCols=( $line ) ;
    echo "${lineCols[0]}"
    echo "${lineCols[1]}"
done < $myFQFileToRead ; 
...

最新更新