2009-09-22 8 views
11

wpadłem na następujący problem: Piszę skrypt bash Linux, który wykonuje następujące czynności:BASH: Strip new-line z ciągiem znaków (czytaj linię)

  • Odczyt linii z pliku
  • Strip \n znak od końca linii po prostu odczytać
  • wykonać polecenie, które jest w środku

Przykład: commands.txt

ls 
ls -l 
ls -ltra 
ps as 

Wykonanie pliku bash powinien dostać pierwszą linię, i wykonać go, ale podczas obecnej \n, powłoka po prostu wyjść „nie znaleziono polecenia: ls” Ta część skryptu wygląda to

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 

Skomentowałeś, że masz rzeczy, które wypróbowałem, zanim zapytam SO. Jakieś rozwiązania? Ja rozbijając sobie głowę dla ostatnich kilku godzin ponad to ...

+0

czy po prostu próbował '$ line' sam? – knittl

+0

Oczywiście, że tak. Ale mówi "polecenie nie znaleziono: ls " –

+0

Wszystko, co jest potrzebne, to: 'myline =" $ (echo -n "$ line") "' (z cytatami zamiast '$()' jeśli chcesz) – jnylen

Odpowiedz

17

Zawsze lubię perl -ne 'chomp and print', do przycinania nowych linii. Ładne i łatwe do zapamiętania.

np. ls -l | perl -ne 'chomp and print'

Jednak

Nie sądzę, że jest tu jednak problem. Chociaż nie jestem pewien, rozumiem, w jaki sposób przekazujesz polecenia w pliku do "odczytu" w twoim skrypcie powłoki.

ze scenariuszem testowym własną rękę tak (test.sh)

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

i przykładowy plik wejściowy tak (test.cmds)

ls 
ls -l 
ls -ltra 

jeśli uruchomię to tak ./test.sh < test.cmds, Widzę oczekiwany wynik, który uruchamia pierwsze polecenie "ls" w bieżącym katalogu roboczym.

Być może twój plik wejściowy zawiera dodatkowe znaki niedrukowalne?

kopalnia wygląda to

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

od dołu komentarze, podejrzewam może być powrotu karetki („R \”) w pliku wejściowego, który nie jest tym samym, co nowego wiersza. Czy plik wejściowy jest oryginalnie w formacie DOS? Jeśli tak, to musisz przekonwertować 2-bajtowe zakończenie linii DOS "\ r \ n" na jednobajtowy UNIX jeden, "\ n", aby osiągnąć oczekiwane wyniki.

Powinieneś być w stanie to zrobić, zamieniając "\ n" na "\ r" w dowolnych wykomentowanych liniach.

+1

Zapomniałem wspomnieć, że plik jest napisany z Windowsa w udziale samby i zupełnie zapomniałem, że powinienem szukać '\ r' zamiast' \ n'. Jeden głos ode mnie i wielkie dzięki! –

0

choć nie pracuje dla ls, polecam zaglądając na find „s -print0 opcja

2

Próbowałem to:

read line 
echo -n $line | od -x 

Dla wejścia 'xxxx', otrzymuję:

0000000 7878 7878 

Jak widać, nie ma \n u koniec zawartości zmiennej. Sugeruję uruchomienie skryptu z opcją -x ((). Spowoduje to wydrukowanie wszystkich poleceń podczas ich wykonywania.

[EDYTOWANIE] Problem polega na tym, że edytowałeś plik commands.txt w systemie Windows. Teraz plik zawiera CRLF (0d0a) jako ograniczniki linii, co wprowadza w błąd read (i ls\r nie jest znaną komendą). Użyj pliku dos2unix lub podobnego, aby przekształcić go w plik uniksowy.

+0

The Rzecz w tym, że nie czytam z klawiatury. Zmieniam mój STDIN na plik (plik command.txt z góry) i jeśli powtórzę linię $ in pomiędzy "I get the output" ls ' –

+0

The ouput I get on 'echo -n $ line | od -x' to "0000000 736c 000d 0000003" –

+1

0d to powrót karetki. Nie to samo co nowa linia – cms

1

trzeba polecenia eval


#!/bin/bash -x 

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

Pobiegłem go jako
./script.sh < plik.txt

I plik.txt było:

 
ls 
ls -l 
ls -ltra 
ps as 
+0

'eval' nie zadziała również –

0

następujący skrypt działa (przynajmniej dla mnie):

#!/bin/bash 

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

Ktoś już napisał program, który wykonuje polecenia powłoki: plik sh

Jeśli naprawdę chcą tylko, aby wykonać pierwszy wiersz pliku: head -n 1 file |sh

Jeśli problem jest karetki powraca: tr -d '\r' <file |sh

+0

Tak, oczywiście, ale ta część mojego pliku wsadowego. To więcej niż proste polecenie wykonania z pliku, bo jeśli to było właśnie to użyłem na pewno tylko 'sh' –

2

możesz także spróbować zastąpić powrotu karetki z newlines tylko przy pomocy poleceń wbudowanych 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'