Bash – 在文本文件中取第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 

İ'M使用此代码

  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列

作为纯粹的shell解决scheme,大文件的cut 速度要快得多 。 如果你的文件是用多个空格分隔的,你可以先删除它们,如:

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

(gnu)sed将用一个spacereplace任何tabspace字符。

对于一个变种 – 这里也是一个perl解决scheme:

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

为了完整:

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

也可以使用一个任意的variables(比如junk )。 重点只是提取列。

演示:

 $ while read _ _ 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 

如果你的文件包含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内build实际上对填充一个数组variables有特殊的支持,你可以这样写:

 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)所build议的,或perl甚至sed )。

一个更简单的变种 –

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

如果你正在使用结构化数据,这还有一个额外的好处,就是不用调用额外的shell进程来运行tr和/或cut等等。 …

(当然,你会想用条件和正常的select来防止错误的input。)

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