2009-09-22 3 views
11

я наткнулся на следующую проблему: Я пишу Баш скрипт для Linux, который делает следующее:BASH: Strip символ новой строки из строки (строки чтения)

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

Пример: commands_empty.txt,

ls 
ls -l 
ls -ltra 
ps as 

Выполнение файла Баш должны получить первую строку, и выполнить его, но в то время как \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 

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

+0

вы просто пытались '$ line' в одиночку? – knittl

+0

Конечно, да. Но он говорит: «команда не найдена: ls » –

+0

Все, что вам нужно: 'myline =" $ (echo -n "$ line") "' (с backquotes вместо '$()' если вы хотите) – jnylen

ответ

17

Мне всегда нравится 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, заканчивающуюся «\ r \ n», в один байт UNIX one, «\ n» для достижения ожидаемых результатов.

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

+1

Я забыл упомянуть, что файл написан из Windows в пакете samba, и я полностью забыл, что я должен искать '\ r' вместо' \ n'. На один голос от меня и огромное спасибо! –

0

, хотя и не работает ls, я рекомендую иметь взгляд на find «s -print0 вариант

2

Я попытался это:

read line 
echo -n $line | od -x 

Для ввода «хххх», я получаю:

0000000 7878 7878 

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

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

+0

Дело в том, что я не читаю с клавиатуры. Я меняю свой STDIN на файл (command.txt сверху), и если я эхо-строку в строке '' Я получаю вывод 'ls ' –

+0

Вывод я получаю на 'echo -n $ line | od -x' является "0000000 736c 000d 0000003" –

+1

0d является возвратом каретки. Не то же самое, что новая строка – cms

1

вам нужно 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 
+0

'eval' тоже не работает –

0

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

#!/bin/bash 

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

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

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

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

+0

Да, конечно, но эта часть моего командного файла. Это больше, чем простая команда выполнения из файла, потому что если бы это было именно так, я использовал, конечно, только 'sh' –

2

вы также можете попытаться заменить возврат каретки с новой строки только с помощью 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'