2009-04-23 7 views
0

Мне нужна помощь в этом сценарии оболочки.Loops in Shell Scripting

  1. Необходимо использовать какой-либо петли.
  2. Необходимо использовать входные данные точно так, как показано на рисунке.
  3. Перенаправление вывода должно выполняться внутри сценария, а не в командной строке.

Вот входные файлы у меня есть: http://pastebin.com/m3f783597

Вот что вывод должен быть: http://pastebin.com/m2c53b25a

Вот моя неудачная попытка: http://pastebin.com/m2c60b41

И это не удалось выход попытка в: http://pastebin.com/m3460e78c

ответ

0

Это домашнее задание, я полагаю?

Читайте на команды сортировки и вставки: man sort, man paste

1

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

Если он обнаружит, что у вас есть плагиатный код, это, вероятно, означает мгновенный сбой.

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

echo -e "Name\t\t On-Call\t\t Phone" 
for daycount in 2 1 4 5 7 6 3 
do 
    for namecount in 3 2 6 1 7 4 5 
    do 
     day=`head -n $daycount p2input2|tail -n 1|cut -f 2 -d " "` 
     name=`head -n $namecount p2input1|tail -n 1|cut -f 1 -d " "` 
     phone=`head -n $namecount p2input1|tail -n 1|cut -f 2 -d " "` 
     echo -e "$name\c" 
     echo -e "\t\t$day\c" 
     echo -e "\t\t$phone" 
     continue 
    done 
done 

И вот намеки:

  • У вас есть две петли, один внутри другого, каждый из которых встречается в 7 раз. Это означает 49 строк вывода, а не 7. Вы хотите обрабатывать каждый день и искать имя и телефон для этого дня (на самом деле имя для этого дня и телефон для этого имени).
  • На самом деле это не подходит для жесткого кодирования простыней (хотя я признаю, что это подлый) - что, если порядок данных изменяется? Лучше искать значения.
  • Вкладки делают вещи беспорядочными, используйте пробелы, а с тех пор выход не зависит от настроек терминала, и вам не нужно беспокоиться о несогласованных вкладках.

И, для полноты картины, вот два входных файлов и ожидаемый результат:

p2input1     p2input2 
========     ======== 
Dave 734.838.9801   Bob Tuesday 
Bob 313.123.4567   Carol Monday 
Carol 248.344.5576  Ted Sunday 
Mary 313.449.1390   Alice Wednesday 
Ted 248.496.2204   Dave Thursday 
Alice 616.556.4458  Mary Saturday 
Frank 634.296.3357  Frank Friday 

Expected output 
=============== 
Name   On-Call   Phone 

carol   monday   248.344.5576 
bob    tuesday   313.123.4567 
alice   wednesday  616.556.4458 
dave   thursday  734.838.9801 
frank   friday   634.296.3357 
mary   saturday  313.449.1390 
ted    sunday   248.496.2204 

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

1 #!/bin/bash 
2 spc20="     " 
3 echo "Name   On-Call   Phone" 
4 echo 
5 for day in monday tuesday wednesday thursday friday saturday sunday 
6 do 
7  name=`grep -i " ${day}$" p2input2 | awk '{print $1}'` 
8  name=`echo ${name} | tr '[A-Z]' '[a-z]'` 
9  bigname=`echo "${name}${spc20}" | cut -c1-15` 
10 
11  bigday=`echo "${day}${spc20}" | cut -c1-15` 
12 
13  phone=`grep -i "^${name} " p2input1 | awk '{print $2}'` 
14 
15  echo "${bigname} ${bigday} ${phone}" 
16 done 

А следующее описание должно помочь:

  • Строка 1 позволяет выбрать правильную оболочку, которая не всегда необходима.
  • Строка 2 дает нам достаточно пространства для упрощения форматирования.
  • Линии 3-4 дают нам название и пустую строку.
  • Линии 5-6 циклов в течение дней, по одному за раз.
  • Строка 7 дает нам имя для дня. 'grep -i " ${day}$"' ищет данный день (независимо от верхнего или нижнего регистра) в конце строки в pinput2, в то время как оператор awk дает вам поле 1 (имя).
  • Строка 8 просто делает имя строчным.
  • Строка 9 создает строку нужного размера для вывода, добавляя 50 пробелов, а затем отсекая все в конце, за исключением 15.
  • Строка 11 делает то же самое в течение дня.
  • Line 13 очень похож на линию 7, за исключением он ищет pinput1, ищет имя на начать строки и возвращает номер телефона в качестве второго поля .
  • Строка 15 выводит только отдельные элементы.
  • Строка 16 завершает цикл.

Итак, у вас есть это, достаточно намеков на (надеюсь) исправить свой собственный код и образец того, как это сделает профессионал :-).

Было бы разумно ознакомиться с используемыми инструментами, grep, tr, cut и awk.

0

Pax дал хороший ответ, но этот код вызывает меньше процессов (11 против 56 = 7 * 8). Он использует файл вспомогательных данных, чтобы указать дни недели и их порядковый номер.

cat <<! >p2input3 
1 Monday 
2 Tuesday 
3 Wednesday 
4 Thursday 
5 Friday 
6 Saturday 
7 Sunday 
! 

sort +1 p2input3 > p2.days 
sort +1 p2input2 > p2.call 
join -1 2 -2 2 p2.days p2.call | sort +2 > p2.duty 
sort +0 p2input1 > p2.body 
join -1 3 -2 1 p2.duty p2.body | sort +2n | tr '[A-Z]' '[a-z]' | 
awk 'BEGIN { printf("%-14s %-14s %s\n", "Name", "On-Call", "Phone"); 
      printf "\n"; } 
      { printf("%-14s %-14s %s\n", $1, $2, $4);}' 
rm -f p2input3 p2.days p2.call p2.duty p2.body 

Команда join является мощным, но требует данные в двух файлах в отсортированном порядке на соединительных ключей. Команда cat дает список дней и номер дня. Первая сортировка помещает этот список в алфавитном порядке имени дня. Второй сорт помещает имена дежурных в алфавитном порядке и в дневное название. Первый присоединиться затем объединяет эти два файла на имя день, а затем сорта на основе имени пользователя, что дает выход:

Wednesday 3 Alice 
Tuesday 2 Bob 
Monday 1 Carol 
Thursday 4 Dave 
Friday 5 Frank 
Saturday 6 Mary 
Sunday 7 Ted 

последний сорт помещает имена и телефонные номера в алфавитном порядке имен. Второе соединение затем объединяет имя + номер телефонного номера с именем + дежурный список, который дает 4 столбца. Это выполняется через tr, чтобы сделать все данные в нижнем регистре, а затем отформатирован с помощью awk, который здесь демонстрирует свою силу и простоту (вместо этого вы можете использовать Perl или Python, но, откровенно говоря, это было бы грязнее).

У Perl есть девиз: TMTOWTDI «Существует несколько способов сделать это».

Это часто применяется и к командам оболочки.


Я полагаю, что мой код не использует петлю ... о, дорогая. Заменить исходную cat команду с:

for day in "1 Monday" "2 Tuesday" "3 Wednesday" "4 Thursday" \ 
      "5 Friday" "6 Saturday" "7 Sunday" 
do echo $day 
done > p2input3 

Теперь это соответствует букве правил.

0

Попробуйте это:

sort file1.txt > file1sort.txt 
sort file2.txt > file2sort.txt 
join file2sort.txt file1sort.txt | column -t > result.txt 
rm file1sort.txt file2sort.txt