2009-09-22 32 views
11

tôi tình cờ gặp những vấn đề sau đây: Tôi đang viết một kịch bản bash Linux mà làm như sau:BASH: Strip mới dòng nhân vật từ chuỗi (đọc dòng)

  • đọc dòng từ tập tin
  • Strip các \n nhân vật từ ngày kết thúc của dòng chỉ đọc
  • Thực hiện lệnh đó là trong đó

Ví dụ: Commands.txt

ls 
ls -l 
ls -ltra 
ps as 

Việc thi hành các tập tin bash sẽ nhận được dòng đầu tiên, và thực hiện nó, nhưng trong khi hiện tại \n, vỏ chỉ kết quả đầu ra "command not found: ls" Đó là một phần của kịch bản trông giống như

này
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 

Đã nhận xét bạn có những điều tôi đã thử trước khi yêu cầu SO. Bất kỳ giải pháp? Tôi đập não của tôi cho các cặp vợ chồng cuối cùng của giờ trên này ...

+0

bạn vừa thử '$ line' một mình chưa? – knittl

+0

Tất nhiên là tôi đã làm. Nhưng nó nói "lệnh không được tìm thấy: ls " –

+0

Tất cả những gì cần là: 'myline =" $ (echo -n "$ line") "' (với backquotes thay vì '$()' nếu bạn muốn) – jnylen

Trả lời

17

Tôi luôn thích perl -ne 'chomp and print', để cắt bớt dòng mới. Đẹp và dễ nhớ.

ví dụ: ls -l | perl -ne 'chomp and print'

Tuy nhiên

Tôi không nghĩ đó là vấn đề của bạn ở đây mặc dù. Mặc dù tôi không chắc chắn tôi hiểu làm thế nào bạn đang đi qua các lệnh trong tập tin thông qua để 'đọc' trong kịch bản shell của bạn.

Với một kịch bản thử nghiệm của riêng tôi như thế này (test.sh)

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

và một tập tin đầu vào mẫu như thế này (test.cmds)

ls 
ls -l 
ls -ltra 

Nếu tôi chạy nó như thế này ./test.sh < test.cmds, tôi thấy kết quả mong đợi, để chạy lệnh đầu tiên 'ls' trên thư mục làm việc hiện tại.

Có lẽ tệp đầu vào của bạn có thêm các ký tự không in được trong đó?

tôi trông như thế này

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

Từ ý kiến ​​của bạn dưới đây, tôi nghi ngờ bạn có thể tự xuống dòng ("\ r") trong tập tin đầu vào của bạn, mà không phải là điều tương tự như một dòng mới. Tệp đầu vào có ở định dạng DOS không? Nếu vậy, sau đó bạn cần phải chuyển đổi dòng DOS 2 byte kết thúc "\ r \ n" thành một byte UNIX đơn, "\ n" để đạt được kết quả mong đợi.

Bạn có thể thực hiện việc này bằng cách hoán đổi "\ n" cho "\ r" trong bất kỳ dòng nhận xét nào của bạn.

+1

Tôi quên đề cập đến tập tin được viết từ Windows trong một phần samba và tôi hoàn toàn quên rằng tôi nên tìm một '\ r' thay vì' \ n'. Lên một phiếu bầu từ tôi và cảm ơn nhiều! –

0

mặc dù không làm việc cho ls, tôi khuyên bạn nên có một cái nhìn tại find 's -print0 tùy chọn

2

Tôi cố gắng này:

read line 
echo -n $line | od -x 

Đối với đầu vào 'xxxx', tôi nhận được:

0000000 7878 7878 

Như bạn thấy, không có \n tại kết thúc nội dung của biến. Tôi đề nghị chạy tập lệnh với tùy chọn -x (bash -x script). Thao tác này sẽ in tất cả các lệnh khi chúng được thực thi.

[EDIT] Vấn đề của bạn là bạn đã chỉnh sửa commands.txt trên Windows. Bây giờ, tệp chứa CRLF (0d0a) làm các dấu phân tách dòng gây nhầm lẫn read (và ls\r không phải là một lệnh đã biết). Sử dụng dos2unix hoặc tương tự để biến nó thành một tệp Unix.

+0

là tôi không đọc từ bàn phím. Tôi thay đổi STDIN của tôi thành một tập tin (command.txt từ trên) và nếu tôi echo dòng $ ở giữa '' tôi nhận được đầu ra 'ls ' –

+0

ouput tôi nhận được trên 'echo -n $ dòng | od -x' là "0000000 736c 000d 0000003" –

+1

0d là trở về vận chuyển. Không giống như một dòng mới – cms

1

bạn cần lệnh eval


#!/bin/bash -x 

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

Tôi chạy nó như
./script.sh < file.txt

Và file.txt là:

 
ls 
ls -l 
ls -ltra 
ps as 
+0

'eval' cũng sẽ không hoạt động –

0

Các kịch bản sau đây công trình (ít nhất là đối với tôi):

#!/bin/bash 

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

Có người đã viết một chương trình mà thực hiện lệnh shell: file sh

Nếu bạn thực sự chỉ muốn thực hiện dòng đầu tiên của một tập tin: head -n 1 file |sh

Nếu vấn đề của bạn là vận chuyển-lợi nhuận: tr -d '\r' <file |sh

+0

Có, tất nhiên, nhưng đó là một phần của tệp lô của tôi. Nó nhiều hơn một lệnh thực thi đơn giản từ tập tin, gây ra nếu nó chỉ là điều này tôi đã sử dụng cho chắc chắn chỉ 'sh' –

2

Bạn cũng có thể thử thay thế các dòng trả về bằng các dòng mới chỉ bằng cách sử dụng các nội trang 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' 
Các vấn đề liên quan