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) как разделители строк, который смущает read
(и ls\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 ;