#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’ <входной файл> выходной файл