我有一个文本文件:
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
它有效,但它非常复杂,需要很长时间才能处理长文本文件。
有更简单的方法吗?
答案 0 :(得分:101)
iirc:
cat filename.txt | awk '{ print $2 $4 }'
或者,如评论中所述:
awk '{ print $2 $4 }' filename.txt
答案 1 :(得分:53)
您可以使用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解决方案的大型文件,cut
更快。如果您的文件使用多个空格分隔,则可以先删除它们,例如:
sed 's/[\t ][\t ]*/ /g' < datafile.txt | cut -d' ' -f3,5
其中(gnu)sed将使用单个tab
替换所有space
或space
个字符。
对于变体 - 这里也是一个perl解决方案:
perl -lanE 'say "$F[2] $F[4]"' < datafile.txt
答案 2 :(得分:21)
为了完整起见:
while read _ _ one _ two _; do
echo "$one $two"
done < file.txt
也可以使用任意变量(例如_
)代替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
答案 3 :(得分:6)
一个更简单的变体 -
$ while read line
do
set $line # assigns words in line to positional parameters
echo "$3 $5"
done < file
答案 4 :(得分:4)
如果您的文件包含 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
)。
答案 5 :(得分:3)
如果您正在使用结构化数据,这还有一个额外的好处,即不调用额外的shell进程来运行tr
和/或cut
或其他东西。 ...
(当然,你会想要用条件和理智的替代方案来防范糟糕的输入。)
...
while read line ;
do
lineCols=( $line ) ;
echo "${lineCols[0]}"
echo "${lineCols[1]}"
done < $myFQFileToRead ;
...