УДАР:Удалить символ новой строки из строки (прочитанная строка)
Вопрос
Я столкнулся со следующей проблемой:Я пишу скрипт Linux bash, который выполняет следующее:
- Прочитать строку из файла
- Разденьте
\n
символ из конца строки просто прочитайте - Выполните команду, которая находится там
Пример:commands.txt
ls
ls -l
ls -ltra
ps as
Выполнение файла bash должно получить первую строку и выполнить ее, но в то время как \n
в настоящее время оболочка просто выводит "команда не найдена:ls"
Эта часть сценария выглядит следующим образом
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
Прокомментировал, что у вас есть то, что я пробовал, прежде чем спросить об этом.Есть какие-нибудь решения?Последние пару часов я ломаю себе голову над этим...
Решение
Мне всегда нравится perl -ne 'chomp and print'
, для обрезки новых строк.Приятный и легко запоминающийся.
например , ls -l | perl -ne 'chomp and print'
Однако
Хотя я не думаю, что это ваша проблема здесь.Хотя я не уверен, что понимаю, как вы передаете команды из файла на "чтение" в вашем сценарии оболочки.
С помощью моего собственного тестового сценария, подобного этому (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
Из ваших комментариев ниже я подозреваю, что у вас могут быть возвраты каретки (" ") в вашем входном файле, что не то же самое, что перевод строки.Является ли входной файл изначально в формате DOS ?Если это так, то вам нужно преобразовать 2-байтовую строку DOS, заканчивающуюся " ", в однобайтовую UNIX-строку " " для достижения ожидаемых результатов.
Вы должны быть в состоянии сделать это, заменив " " на " " в любой из ваших закомментированных строк.
Другие советы
Кто-то уже написал программу, которая выполняет команды оболочки:файл sh
Если вы действительно хотите выполнить только первую строку файла: head -n 1 file |sh
Если ваша проблема заключается в возврате каретки: tr -d '\r' <file |sh
Я попробовал это:
read line
echo -n $line | od -x
Для ввода 'xxxx' я получаю:
0000000 7878 7878
Как вы можете видеть, здесь нет \n
в конце содержимого переменной.Я предлагаю запустить скрипт с опцией -x
(bash -x script
).При этом будут выводиться все команды по мере их выполнения.
[РЕДАКТИРОВАТЬ] Ваша проблема в том, что вы отредактировали commands.txt в Windows.Теперь файл содержит CRLF (0d0a) в качестве разделителей строк, что сбивает с толку read
(и ls\r
не является известной командой).Использование dos2unix
или аналогично, чтобы превратить его в файл Unix.
Вы также можете попытаться заменить возврат каретки переводом строк только с помощью встроенных 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'
вам нужна команда 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
хотя и не работает на ls
, Я рекомендую взглянуть на find
’s -print0
вариант
Следующий скрипт работает (по крайней мере, для меня):
#!/bin/bash
while read I ; do if [ "$I" ] ; then $I ; fi ; done ;