Ответ 1
iirc:
cat filename.txt | awk '{ print $2 $4 }'
или, как указано в комментариях:
awk '{ print $2 $4 }' filename.txt
У меня есть текстовый файл:
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
Я хочу взять 2-е и 4-е слово каждой строки следующим образом:
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
намного быстрее для больших файлов в качестве чистого решения оболочки. Если ваш файл разделен несколькими пробелами, вы можете сначала удалить их, например:
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
Для полноты:
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
Еще один простой вариант -
$ while read line
do
set $line # assigns words in line to positional parameters
echo "$3 $5"
done < file
Если ваш файл содержит n строк, ваш script должен прочитать файл n раз; поэтому, если вы удваиваете длину файла, вы в четыре раза увеличиваете объем работы, которую выполняет ваш script — и почти вся эта работа просто отбрасывается, так как все, что вы хотите сделать, это цикл по строкам по порядку.
Вместо этого наилучшим способом петли над строками файла является использование цикла while
, при этом команда condition является read
builtin:
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
, как предлагает Том ван дер Вёрдт, или perl
, или даже sed
).
Если вы используете структурированные данные, это имеет дополнительное преимущество, не вызывая дополнительный процесс оболочки для запуска tr
и/или cut
или что-то еще....
(Конечно, вы захотите защитить от плохих входов с условностями и разумными альтернативами.)
...
while read line ;
do
lineCols=( $line ) ;
echo "${lineCols[0]}"
echo "${lineCols[1]}"
done < $myFQFileToRead ;
...