我有一个文本文件:
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
替换任何tab
或space
字符。
对于一个变量-这里也有一个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 ;
...