Bash: читать файл построчно и обрабатывать каждый сегмент как параметры для другой программы - PullRequest
35 голосов
/ 01 октября 2011

У меня есть грязная работа, поэтому Bash-скрипт кажется хорошим выбором.Я новичок в Bash, и этот опыт меня расстраивает.

Файл mapfiles.txt состоит из следующих строк.Каждая строка имеет четыре сегмента, разделенных пробелом.Каждый сегмент представляет входной параметр для внешнего имени программы «prog».Например, «cm19_1.png» - это имя файла , «0001» - индекс , «121422481» - долгота , а «31035995» - широта .

Файл: mapfiles.txt

cm19_1.png 0001 121422481 31035995
cm19_2.png 0002 121423224 31035995
cm19_3.png 0003 121423967 31035995
…

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

[Usage] prog <index> <longitude> <latitude> <filename>
example: prog 0001 121422481 31035995 cm19_1.png

Обычно сценарий bash будет работать следующим образом:

  1. Считывание одной строки из файлов карт.txt
  2. Разделить сегменты
  3. Вызвать прогу с правильным порядком параметров

Вот идет run.sh.

#!/bin/sh

input=mapfiles.txt
cmd=prog

while read line
do
        file=$(echo $line | cut -d' ' -f1)
        key=$(echo $line | cut -d' ' -f2)
        log=$(echo $line | cut -d' ' -f3)
        lat=$(echo $line | cut -d' ' -f4)
        echo $cmd $key $log $lat $file
done < "$input"

Что яожидается

prog 0001 121422481 31035995 cm19_1.png
prog 0002 121423224 31035995 cm19_2.png
prog 0003 121423967 31035995 cm19_3.png
… 

Фактический результат, который я получил:

 cm19_1.png21422481 31035995
 cm19_2.png21423224 31035995
 cm19_3.png21423967 31035995

Проблемы, которые меня смутили

  1. Где находится прога?
  2. Где пробел?
  3. Что не так с порядком параметров?

Хмм ... Я написал этот скрипт на моем Mac с помощью vim и скопировал его вНаучный Linux box и gentoo box.Эти три парня получают одинаковые смешные результаты.

Ответы [ 3 ]

48 голосов
/ 01 октября 2011

Вы можете упростить это много:

while read file key log lat
do
  echo "$cmd" "$key" "$log" "$lat" "$file"
done < "$input"
9 голосов
/ 03 октября 2011

Используя GNU Parallel, вы можете сделать это в одну строку + вы получите это параллельно бесплатно:

cat mapfile.txt | parallel --colsep '\s' prog {2} {3} {4} {1}

Посмотрите вступительные видео, чтобы узнать больше: http://www.youtube.com/watch?v=OpaiGYxkSuQ

2 голосов
/ 01 октября 2011

prog мог исчезнуть, потому что $cmd не экспортируется. Ваша версия / bin / sh может выполнить оператор while в отдельной оболочке. Этого не должно быть, и это не относится к моей установке bash, но, возможно, в этом отделе вы ведете себя интересно.

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

Я скопировал и вставил ваш скрипт и ваш исходный файл в мой пакет gentoo, и он дает ожидаемые результаты. Возможно, вам следует сделать то же самое и сравнить файлы с исходными.

...