Сбой теста оператора If при сравнении чисел, считанных из файла

#bash #if-statement

#bash #if-statement

Вопрос:

У меня есть файл со следующими входными данными (пример не полного файла)

 JANE,SMITH,12,1000298,2
CLARA,OSWALD,10,10890298,4
  

У нас есть FirstName , Lastname , Grade ID , School и, ,,. У меня есть цикл, который считывает каждое из них в свою собственную переменную. Последнее число (2,4) указывает, к какой школе они принадлежат, и у меня есть код, который изменяет 2 на HS и 4 на ML . Мне нужно пройти тест. Где, если он обнаружит, что 2 сделайте это, найдите 3 сделайте это и так далее.

 #!bin/bash
OLDIFS=$IFS
IFS=","

while read  First_Name Last_Name Grade Student_Id school
do 


 if [[ $school == 2 ]]
    then
        School=$(echo $school | sed -e 's/2/HS/g')
    elif [[ $school == 3 ]]
     then
        School=$(echo $school | sed -e 's/3/MI/g')
      else
       School=$(echo $school | sed -e 's/4/ML/g')
   fi
   echo $First_Name $Last_Name $Grade $Student_Id $School
done < $1
IFS=$OLDIFS
  

ОК. Итак, школа имеет 2,4 в соответствии с вводом из файла. Когда он находит 2, он должен изменить это 2 на HS. Но тест завершается неудачей. Даже если я использую -eq , это завершается неудачей. Я добавляю "" просто чтобы посмотреть, не помогло ли это что-нибудь, но ничего. Когда я повторяю $school , он выдает мне правильные числа 2,4, но сравнить их не удается.
Правильный вывод

 JANE,SMITH 12 1000298 HS
CLARA OSWALD 10 10890298 ML
  

Что я получаю, так это

 CLARA OSWALD 10 10890298 ML
  

Поскольку он переходит прямо к части else. Он не проверяет первое. И если я попытаюсь проверить $school == 4 or ( -eq ), это тоже не сработает.

Комментарии:

1. Дорогой Джон Доу, добро пожаловать в Stack Overflow. Очень хороший вопрос и хорошо объяснил, в чем проблема. Продолжайте в том же духе и используйте рекомендации Доктора Кто! Также взгляните на shellcheck.net , что уже очень поможет вам.

2. Более того, похоже, что ваша ошибка неверна. Попробуйте записать #!/usr/bin/env bash (у вас не хватало косой черты в начале вашей первой строки). Когда я исправляю это, у меня это работает.

3. Бьюсь об заклад, что ваш файл данных имеет окончания строк CRNL в стиле DOS, так что на самом деле $ school является 2r , и вы не сможете обнаружить это невооруженным глазом. Запустите dos2unix как файл данных, так и файл сценария и убедитесь, что ваш текстовый редактор сохраняет файлы с окончаниями строк unix.

4. Кроме того, в зависимости от того, как вы выполняете скрипт, он будет выполняться в отдельном процессе, поэтому вам не нужно создавать резервную копию и восстанавливать значение IFS.

5. if [ "$a" -eq "$b" ] следует использовать при сравнении 2 целых чисел. Для получения дополнительной информации об операторах сравнения bash, пожалуйста, смотрите: Ссылка .

Ответ №1:

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

входной файл

 JANE,SMITH,12,1000298,2
CLARA,OSWALD,10,10890298,4
DONALD,DUCK,10,10890298,3
DAISY,DUCK,10,10890298,2
  

скрипт

 IFS=","                          # set field separator
while read line; do              # read all line
   set -- $line                  # split lines
   case $5 in                    # depending on last value in line
      2) school="HS";;           # choose the school form
      3) school="MI";;
      4) school="ML";;
   esac
   echo "$1,$2 $3 $4 $school"    # print output
done < inputfile                 # read from inputfile
  

вывод

 JANE,SMITH 12 1000298 HS
CLARA,OSWALD 10 10890298 ML
DONALD,DUCK 10 10890298 MI
DAISY,DUCK 10 10890298 HS
  

Комментарии:

1. Вы захотите сделать set -f , чтобы отключить расширение имени файла для без кавычек set -- $line — если одно из полей является * , вы не хотите заменять список имен файлов.

2. Но если мы позволим себе ограничиться bash, while IFS=, read -ra fields обойдет риск расширения имени файла.

3. То, что у вас есть, действительно работает. Похоже, @glenn jackman может быть прав. Если я использую ваш код с имеющимся у меня файлом, он стирает последнее число и печатает только JANE, SMITH 12 1000298. Но если я использую ваш входной файл, это работает. Но я понятия не имею, как решить эту проблему.

4. Я предоставил ответ в своем комментарии. Прочитайте man dos2unix и расскажите мне, что вы узнали.

5. @glennjackman Я, честно говоря, не понимаю dos2unix. У Mac нет этого на своей справочной странице. И когда я просмотрел это, для меня это все еще не имело смысла. В итоге я использовал tr -d ‘r’ <входной файл> выходной файл