сценарий оболочки – команда echo не печатает в правильной последовательности

У меня есть следующий testfile.txt :

 string1 1 string2 2 string3 3 string1 2 string2 4 string3 6 string1 3 string2 6 string3 9 

У меня есть следующий скрипт:

 #!bin/sh oldstr="abc" while read line do newstr=\`echo "$line" | sed 's/\(.*\)\( \)\([0-9].*\)/\1/'\` echo "$oldstr vs $newstr" if [ $oldstr == $newstr ] then echo "old $oldstr" else oldstr=$newstr echo "new $oldstr" fi done < $@ | sort echo "done" 

Затем я запускаю скрипт:

 $ sh test.sh testfile.txt 

и получить результат:

 abc vs string1 new string1 new string1 new string1 new string2 new string2 new string2 new string3 new string3 new string3 string1 vs string2 string1 vs string2 string1 vs string2 string2 vs string3 string2 vs string3 string2 vs string3 string3 vs string1 string3 vs string1 done 

Я хотел бы знать, почему, поскольку я ожидаю, что результат будет следующим:

 abc vs string1 new string1 string1 vs string1 old string1 string1 vs string1 old string1 string1 vs string2 new string2 

и так далее.

  1. Почему не работает оператор «if»?
  2. Почему эхо-печать выходит из строя?

1) они вышли из строя, потому что вы его спросили: вы готовите весь список, а затем | sort | sort их.

2) тест должен быть (стандартный синтаксис sh ): if [ "$variable" = ... (not == ).

3) для проверки вещей используйте sh -xv который будет печатать каждую строку перед ее исполнением и результат разложений.

4) почему вы избегаете обратных шагов?

5) У вас отсутствуют котировки вокруг переменных

6) < $@ работает только в том случае, если в скрипте есть только один аргумент.

7), используя read без -r и без удаления пробельных символов из $IFS вероятно, здесь не имеет смысла.

8) вы не можете использовать echo с произвольными данными

9) Это должно быть #!/bin/sh , а не #!bin/sh

Рабочий скрипт:

 #!/bin/sh oldstr="abc" while IFS= read -r line do newstr=`printf '%s\n' "$line" | sed 's/\(.*\)\( \)\([0-9].*\)/\1/'` printf '%s\n' "$oldstr vs $newstr" if [ "$oldstr" = "$newstr" ] then echo "old $oldstr" else oldstr=$newstr printf '%s\n' "new $oldstr" fi done < "$1" echo "done" 

Кроме того, вы должны изменить входной тестовый файл. Тот, который вы опубликовали, никогда не запускает «старый» случай.

Если вы хотите отсортировать файл перед его передачей в цикл, измените строку while на:

 sort -- "$@" | while IFS= read -r line 

и, очевидно, удалите < $@ после done :

 sort -- "$@" | while IFS= read -r line do [...] done