Как сделать сумму из файла и переместить определенным образом в другой файл в Linux? - PullRequest
3 голосов
/ 17 ноября 2011

На самом деле это мое задание. У меня есть три-четыре файла, связанные с записями студентов. Каждый файл имеет две-три записи студентов. Вот так

Course Name:Opreating System
Credit: 4
123456 1 1 0 1 1 0 1 0 0 0 1 5 8 0 12 10 25
243567 0 1 1 0 1 1 0 1 0 0 0 7 9 12 15 17 15

У каждого файла свое имя.Имя курсора и студента перемещаются в одном файле, но теперь я не знаю, как добавить все метки и перейти в другой файл в том же месте, где находится идентификатор?Подскажите, пожалуйста, как это сделать?

Это выглядит так:

Student# Operating Systems JAVA C++ Web Programming GPA
123456       76             63   50       82        67.75
243567       80             -    34       63          59

Я так и сделал:

#!/bin/sh

find ~/2011/Fall/StudentsRecord -name "*.rec" | xargs grep -l 'CREDITS' | xargs cat > rsh1

echo "STUDENT ID" > rsh2

sed -n /COURSE/p rsh1 | sed 's/COURSE NAME: //g' >> rsh2

echo "GPA" >> rsh2

sed -e :a -e '{N; s/\n/       /g; ta}' rsh2 > rshf

sed '/COURSE/d;/CREDIT/d' rsh1 | sort -uk 1,1 | cut -d' ' -f1 | paste -d' ' >> rshf

1 Ответ

2 голосов
/ 17 ноября 2011

Некоторые комментарии и несколько указателей:

Было бы полезно добавить «комментарии» для каждой строки кода, которая не является самоочевидной; то есть код типа mv f f.bak не нужно комментировать, но я не уверен, какова цель ваших многочисленных строк кода.

Вы вставляете комментарий с символом '#', например

#  concatenate all files that contain the word CREDITS into a file called rsh1
find ~/2011/Fall/StudentsRecord -name "*.rec" | xargs grep -l 'CREDITS' | xargs cat > rsh1

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

`grep -l 'Credits'` 

ИЛИ сказать grep -i (регистр gnore), т.е.

`grep -il 'Credits'

Ваша линия

sed -n /COURSE/p rsh1 | sed 's/COURSE NAME: //g' >> rsh2

можно уменьшить до 1 обращения к sed (и у вас происходит то же самое, что и в случае с запутанностью), попробуйте

sed -n '/COURSE/i{;s/COURSE NAME: //gip;}' rsh1 >> rsh2

Это означает (-n по умолчанию не печатать каждую строку),

`gip` = global substitute, 
      = ignore case in matching
        print only lines where substituion was made

Таким образом, вы редактируете строку ИМЯ КУРСА для любой строки, в которой есть КУРС, и печатаете только эти строки '(вам, вероятно, не нужен спецификатор' g '(глобальный), учитывая, что вы ожидаете только 1 экземпляр за строку)

Ваша линия

 sed -e :a -e '{N; s/\n/       /g; ta}' rsh2 > rshf

На самом деле выглядит довольно неплохо, очень продвинуто, вы пытаетесь «сложить» каждые 2 строки в одну строку, верно?

Но,

sed '/COURSE/d;/CREDIT/d' rsh1 | sort -uk 1,1 | cut -d' ' -f1 | paste -d' ' >> rshf

Я действительно смущен этим, вы пытаетесь подсчитать баллы студентов? (со встроенным видом, я думаю, нет). Почему вы думаете, что вам нужна сортировка,

Хотя можно выполнять арифметику в sed, это очень сложно, поэтому вы можете либо использовать переменные bash для вычисления значений, либо использовать инструмент unix, предназначенный для обработки текста и выполнения логических и математических операций здесь представлены данные, awk или perl

В любом случае, одним из решений для подсчета каждого балла является использование awk

 echo "123456 1 1 0 1 1 0 1 0 0 0 1 5 8 0 12 10 25" |\
 awk '{for (i=2;i<=NF;i++) { tot+=$i }; print $1 "\t" tot }'  

Даст вам подсказку, как поступить в этом направлении.

Awk имеет предопределенные переменные, которые он заполняет для каждого файла и каждой строки текста, которую он читает, т.е.

$0 = complete line of text (as defined by the internal variables RS (RecordSeparator)
                             which defaults to '\n' new-line char, the unix end-of-line char

$1 = first field in text (as defined by the internal variables FS (FieldSeparator)
                           which defaults to (possibly multiple) space chars OR tab char
                          a line with 2 connected spaces chars and 1 tab char has 3 fields)

NF = Number(of)Fields in current line of data (again fields defined by value of FS as 
                                                described above)

(there are many others, besides, $0, $n, $NF, $FS, $RS).

Вы можете программно увеличивать значения, такие как $ 1, $ 2, $ 3, используя переменную, как в примере кода, например, $ i (i - это переменная с числом от 2 до NF. Ведущий '$' говорит, дайте мне значение поля я (то есть $ 2, $ 3, $ 4 ...)

Кстати, ваша проблема может быть легко решена с помощью одного сценария awk, но, очевидно, вы должны узнать о cat, cut, grep и т. Д., Что является очень стоящей целью.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...