Перебор содержимого файла в Bash

Как выполнить итерацию каждой строки текстового файла с помощью Bash?

С помощью этого сценария:

echo "Start!"
for p in (peptides.txt)
do
    echo "${p}"
done

Я получаю такой вывод на экран:

Start!
./runPep.sh: line 3: syntax error near unexpected token `('
./runPep.sh: line 3: `for p in (peptides.txt)'

(Позже я захочу сделать с $p что-то более сложное, чем просто вывод на экран).


Переменная среды SHELL является (из env):

SHELL=/bin/bash

/bin/bash --version выход:

GNU bash, version 3.1.17(1)-release (x86_64-suse-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.

cat /proc/version output:

Linux version 2.6.18.2-34-default (geeko@buildhost) (gcc version 4.1.2 20061115 (prerelease) (SUSE Linux)) #1 SMP Mon Nov 27 11:46:27 UTC 2006

Файл peptides.txt содержит:

RKEKNVQ
IPKKLLQK
QYFHQLEKMNVK
IPKKLLQK
GDLSTALEVAIDCYEK
QYFHQLEKMNVKIPENIYR
RKEKNVQ
VLAKHGKLQDAIN
ILGFMK
LEDVALQILL
Комментарии к вопросу (1)
Решение

Один из способов сделать это:


while read p; do
  echo "$p"
done 
Комментарии (22)
cat peptides.txt | while read line 
do
   # do something with $line here
done

и вариант с одной фразой:

cat peptides.txt | while read line; do something_with_$line_here; done

Эти опции пропускают последнюю строку файла, если в ней нет перевода строки.

Вы можете избежать этого следующим образом:

cat peptides.txt | while read line || [[ -n $line ]];
do
   # do something with $line here
done
Комментарии (21)

Вариант 1a: Цикл While: По одной строке за раз: Перенаправление ввода

#!/bin/bash
filename='peptides.txt'
echo Start
while read p; do 
    echo $p
done < $filename

Опция 1b: Цикл While: По одной строке за раз: Открыть файл, прочитать из дескриптора файла (в данном случае дескриптор файла #4).


#!/bin/bash
filename='peptides.txt'
exec 4
Комментарии (6)

Это не лучше, чем другие ответы, но еще один способ, чтобы получить работу в файл без пробелов (см. комментарии). Я считаю, что мне часто нужен один-лайнеры, чтобы копаться в списки в текстовых файлах, не используя отдельных файлах скрипта.

for word in $(cat peptides.txt); do echo $word; done

Этот формат позволяет мне поставить все это в одной командной строке. Изменить "Эхо $слово" Какая часть к тому, что вы хотите, и вы можете выдать несколько команд, разделенных точкой с запятой. В следующем примере используется файл'ы содержание в качестве аргументов в двух других сценариев, которые вы писали.

for word in $(cat peptides.txt); do cmd_a.sh $word; cmd_b.py $word; done

Или если вы собираетесь использовать это как редактор потока (узнать СЭД) вы можете сбросить вывода в другой файл следующим образом.

for word in $(cat peptides.txt); do cmd_a.sh $word; cmd_b.py $word; done > outfile.txt

Я've использовали их как написано выше, потому что я использовал текстовые файлы, где я'вэ, созданных их с одно слово в каждой строке. (См. комментарии) Если у вас есть пробелы, которые вы не'т хотим, чтобы разделять ваших слов/строк, это становится немного страшнее, но ту же команду по-прежнему работает следующим образом:

OLDIFS=$IFS; IFS=$'\n'; for line in $(cat peptides.txt); do cmd_a.sh $line; cmd_b.py $line; done > outfile.txt; IFS=$OLDIFS

Это просто говорит оболочке для разделения на строки, а не пробелы, а затем возвращает в среду до того, что было ранее. На данный момент, Вы, возможно, захотите положить все это в сценарий оболочки, а не сжимая все в одну строку, хотя.

Удачи!

Комментарии (10)

Еще несколько вещей, которые не охвачены другими ответы:

Чтение из файла с разделителями

# ':' is the delimiter here, and there are three fields on each line in the file
# IFS set below is restricted to the context of `read`, it doesn't affect any other code
while IFS=: read -r field1 field2 field3; do
  # process the fields
  # if the line has less than three fields, the missing fields will be set to an empty string
  # if the line has more than three fields, `field3` will get all the values, including the third field plus the delimiter(s)
done < input.txt

Чтение из вывода другой команды, используя процесс замещения


while read -r line; do
  # process the line
done < 
Комментарии (1)

Использовать цикл while, как это:


while IFS= read -r line; do
   echo "$line"
done 
Комментарии (7)

Если вы Don'т хотите, чтобы ваши читать, чтобы быть сломанной символ новой строки, используйте -

#!/bin/bash
while IFS='' read -r line || [[ -n "$line" ]]; do
    echo "$line"
done < "$1"

Затем запустите скрипт с именем файла в качестве параметра.

Комментарии (0)

Предположим, у вас есть этот файл:

$ cat /tmp/test.txt
Line 1
    Line 2 has leading space
Line 3 followed by blank line

Line 5 (follows a blank line) and has trailing space    
Line 6 has no ending CR

Есть четыре элемента, которые будет изменять значение выходной файл прочитан многими Баш решений:

  1. Пустая строка 4;
  2. Ведущих или конечных пробелов в двух строках;
  3. Поддержание смысл отдельных строк (т. е. каждая строка-это запись);
  4. Линии 6, не прекращается с ПР.

Если вы хотите, чтобы текстовый файл построчно, включая пустые строки и завершения линии без CR, вы должны использовать цикл while, и вы должны иметь альтернативный тест для итоговой строки.

Вот несколько методов, которые могут изменить файл (в сравнении с тем, что " кот " возвращает):

  1. потерять последнюю строку и пробелы в начале и конце:

$ while read -r p; do printf "%s\n" "'$p'"; done 
Комментарии (1)
#!/bin/bash
#
# Change the file name from "test" to desired input file 
# (The comments in bash are prefixed with #'s)
for x in $(cat test.txt)
do
    echo $x
done
Комментарии (2)

Вот мой реальный пример из жизни, как петля линиям другого выхода программы, проверить на подстроки, падение двойные кавычки из переменной, использовать эту переменную вне цикла. Я думаю, довольно многие спрашивают эти вопросы рано или поздно.


##Parse FPS from first video stream, drop quotes from fps variable
## streams.stream.0.codec_type="video"
## streams.stream.0.r_frame_rate="24000/1001"
## streams.stream.0.avg_frame_rate="24000/1001"
FPS=unknown
while read -r line; do
  if [[ $FPS == "unknown" ]] && [[ $line == *".codec_type=\"video\""* ]]; then
    echo ParseFPS $line
    FPS=parse
  fi
  if [[ $FPS == "parse" ]] && [[ $line == *".r_frame_rate="* ]]; then
    echo ParseFPS $line
    FPS=${line##*=}
    FPS="${FPS%\"}"
    FPS="${FPS#\"}"
  fi
done 
Комментарии (1)

Это скорее очень поздно, но с мыслью, что это может помочь кому-то, я добавляю ответ. Также это может не быть лучший способ. начальник команды может быть использован с `-н аргументом для чтения Нлинии от начала файла и команду также "хвост" может быть использован для чтения снизу. Теперь, чтобы принести энной строку из файла, то руководителя n строк, передать сведения в хвост только 1 строку из водопроводной данных.


   TOTAL_LINES=`wc -l $USER_FILE | cut -d " " -f1 `
   echo $TOTAL_LINES       # To validate total lines in the file

   for (( i=1 ; i 
Комментарии (0)

@Петр: это может работать для вас

echo "Start!";for p in $(cat ./pep); do
echo $p
done

Это будет выход-

Start!
RKEKNVQ
IPKKLLQK
QYFHQLEKMNVK
IPKKLLQK
GDLSTALEVAIDCYEK
QYFHQLEKMNVKIPENIYR
RKEKNVQ
VLAKHGKLQDAIN
ILGFMK
LEDVALQILL
Комментарии (7)