BASH: Снять новый символ строки из строки (строка чтения)

Я столкнулся с следующей проблемой: я пишу Linux bash script, который делает следующее:

  • Чтение строки из файла
  • Разделите символ \n с конца строки только что прочитанной
  • Выполните команду, которая там

Пример: Commands.txt

ls
ls -l
ls -ltra
ps as

Выполнение файла bash должно получить первую строку и выполнить его, но пока \n присутствует, оболочка просто выводит "команда не найдена: ls" Эта часть script выглядит так:

 read line

        if [ -n "$line" ]; then #if not empty line

                #myline=`echo -n $line | tr -d '\n'`
                #myline=`echo -e $line | sed ':start /^.*$/N;s/\n//g; t start'`

                myline=`echo -n $line | tr -d "\n"`
                $myline  #execute it

                cat $fname | tail -n+2 > $fname.txt
                mv $fname.txt $fname
        fi

Прокомментировал, что у вас есть вещи, которые я пробовал, прежде чем спросить. Любые решения? Я размахиваю мозгами последние пару часов над этим...

Ответ 1

Мне всегда нравится perl -ne 'chomp and print', для обрезки строк. Приятно и легко запомнить.

например. ls -l | perl -ne 'chomp and print'

Однако

Я не думаю, что это ваша проблема здесь. Хотя я не уверен, что понимаю, как вы передаете команды в файле до "чтения" в своей оболочке script.

С тестом script моего собственного типа (test.sh)

read line
if [ -n "$line" ]; then
  $line
fi

и примерный входной файл, подобный этому (test.cmds)

ls 
ls -l
ls -ltra

Если я запустил его так: ./test.sh < test.cmds, я вижу ожидаемый результат, который должен запускать первую команду 'ls' в текущем рабочем каталоге.

Возможно, ваш входной файл содержит в нем дополнительные непечатаемые символы?

моя выглядит так

od -c test.cmds 
0000000    l   s      \n   l   s       -   l  \n   l   s       -   l   t
0000020    r   a  \n                                                    
0000023

Из ваших комментариев ниже, я подозреваю, что вы можете иметь возврат каретки ( "\ r" ) в свой входной файл, что не то же самое, что и в новой строке. Является ли исходный файл первоначально в формате DOS? Если это так, вам нужно преобразовать 2-байтовую строку DOS, заканчивающуюся "\ r\n", в один байт UNIX one, "\n" для достижения ожидаемых результатов.

Вы должны сделать это, заменив "\n" на "\ r" в любой из прокомментированных строк.

Ответ 2

Кто-то уже написал программу, которая выполняет команды оболочки: sh файл

Если вы действительно хотите только выполнить первую строку файла: head -n 1 file |sh

Если ваша проблема - возврат каретки: tr -d '\r' <file |sh

Ответ 3

Я пробовал это:

read line
echo -n $line | od -x

Для ввода "xxxx" я получаю:

0000000 7878 7878

Как вы можете видеть, в конце содержимого переменной нет \n. Я предлагаю запустить script с опцией -x (bash -x script). Это будет печатать все команды по мере их выполнения.

[EDIT] Ваша проблема в том, что вы отредактировали файл command.txt в Windows. Теперь файл содержит CRLF (0d0a) как разделители строк, который смущает readls\r не является известной командой). Используйте dos2unix или аналогичный, чтобы превратить его в файл Unix.

Ответ 4

Вы также можете попытаться заменить возврат каретки символами новой строки только с помощью Bash встроенных функций:

line=$'a line\r' 
line="${line//$'\r'/$'\n'}" 
#line="${line/%$'\r'/$'\n'}"       # replace only at line end
printf "%s" "$line" | ruby -0777 -n -e 'p $_.to_s' 

Ответ 5

вам нужна команда eval


#!/bin/bash -x

while read  cmd
do
 if [ "$cmd" ]
 then
  eval "$cmd"
 fi
done

Я запустил его как . / script.sh < file.txt

И file.txt был:

ls
ls -l
ls -ltra
ps as

Ответ 6

хотя и не работает для ls, я рекомендую посмотреть find s -print0 option

Ответ 7

Следующий script работает (по крайней мере, для меня):

#!/bin/bash

while read I ; do if [ "$I" ] ; then $I ; fi ; done ;