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将用一个space
replace任何tab
或space
字符。
对于一个变种 – 这里也是一个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 ; ...