2013-10-16 18 views
6

Tôi đã viết một kịch bản lệnh shell trong ksh để chuyển đổi tệp CSV thành tệp XML bảng tính. Nó lấy một tệp CSV hiện có (đường dẫn đến đó là một biến trong kịch bản lệnh), và sau đó tạo một tệp đầu ra mới .xls. Tập lệnh không có tham số vị trí. Tên tệp của CSV hiện được mã hóa cứng vào tập lệnh.Đầu vào ống vào một tập lệnh

Tôi muốn sửa đổi tập lệnh để có thể lấy dữ liệu CSV đầu vào từ một đường ống và do đó dữ liệu đầu ra .xls cũng có thể được chuyển hướng hoặc chuyển hướng (>) sang tệp trên dòng lệnh.

Điều này đạt được như thế nào?

Tôi đang cố gắng tìm tài liệu về cách viết tập lệnh trình bao để nhập liệu từ một đường ống. Có vẻ như 'đọc' chỉ được sử dụng cho đầu vào std từ kb.

Cảm ơn.

Edit: kịch bản dưới đây để biết (nay được sửa đổi để lấy đầu vào từ một ống thông qua con mèo, theo câu trả lời cho câu hỏi

#!/bin/ksh 
#Script to convert a .csv data to "Spreadsheet ML" XML format - the XML scheme for Excel 2003 
# 
# Take CSV data as standard input 
# Out XLS data as standard output 
# 

DATE=`date +%Y%m%d` 

#define tmp files 
INPUT=tmp.csv 
IN_FILE=in_file.csv 

#take standard input and save as $INPUT (tmp.csv) 
cat > $INPUT 

#clean input data and save as $IN_FILE (in_file.csv) 
grep '.' $INPUT | sed 's/ *,/,/g' | sed 's/, */,/g' > $IN_FILE 

#delete original $INPUT file (tmp.csv) 
rm $INPUT 

#detect the number of columns and rows in the input file 
ROWS=`wc -l < $IN_FILE | sed 's/ //g' ` 
COLS=`awk -F',' '{print NF; exit}' $IN_FILE` 
#echo "Total columns is $COLS" 
#echo "Total rows is $ROWS" 

#create start of Excel File 
echo "<?xml version=\"1.0\"?> 
<?mso-application progid=\"Excel.Sheet\"?> 
<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\" 
     xmlns:o=\"urn:schemas-microsoft-com:office:office\" 
     xmlns:x=\"urn:schemas-microsoft-com:office:excel\" 
     xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\" 
     xmlns:html=\"http://www.w3.org/TR/REC-html40\"> 
<DocumentProperties xmlns=\"urn:schemas-microsoft-com:office:office\"> 
     <Author>Ben Hamilton</Author> 
     <LastAuthor>Ben Hamilton</LastAuthor> 
     <Created>${DATE}</Created> 
     <Company>MCC</Company> 
     <Version>10.2625</Version> 
</DocumentProperties> 
<ExcelWorkbook xmlns=\"urn:schemas-microsoft-com:office:excel\"> 
     <WindowHeight>6135</WindowHeight> 
     <WindowWidth>8445</WindowWidth> 
     <WindowTopX>240</WindowTopX> 
     <WindowTopY>120</WindowTopY> 
     <ProtectStructure>False</ProtectStructure> 
     <ProtectWindows>False</ProtectWindows> 
</ExcelWorkbook> 

<Styles> 
     <Style ss:ID=\"Default\" ss:Name=\"Normal\"> 
      <Alignment ss:Vertical=\"Bottom\" /> 
      <Borders /> 
      <Font /> 
      <Interior /> 
      <NumberFormat /> 
      <Protection /> 
     </Style> 
     <Style ss:ID=\"AcadDate\"> 
     <NumberFormat ss:Format=\"Short Date\"/>  
     </Style> 
</Styles> 
<Worksheet ss:Name=\"Sheet 1\"> 
<Table> 
<Column ss:AutoFitWidth=\"1\" />" 

#for each row in turn, create the XML elements for row/column 
r=1 
while ((r <= $ROWS)) 
do 
    echo "<Row>\n" 
    c=1 
    while ((c <= $COLS)) 
    do 
     DATA=`sed -n "${r}p" $IN_FILE | cut -d "," -f $c ` 

     if [[ "${DATA}" == [0-9][0-9]\.[0-9][0-9]\.[0-9][0-9][0-9][0-9] ]]; then 

      DD=`echo $DATA | cut -d "." -f 1` 
      MM=`echo $DATA | cut -d "." -f 2` 
      YYYY=`echo $DATA | cut -d "." -f 3`  
      echo "<Cell ss:StyleID=\"AcadDate\"><Data ss:Type=\"DateTime\">${YYYY}-${MM}-${DD}T00:00:00.000</Data></Cell>" 
     else   
      echo "<Cell><Data ss:Type=\"String\">${DATA}</Data></Cell>" 
     fi 
     ((c+=1)) 
    done 
    echo "</Row>" 
    ((r+=1)) 
done 

echo "</Table>\n</Worksheet>\n</Workbook>" 


rm $IN_FILE > /dev/null 

exit 0 
+0

Hiển thị tập lệnh ... – devnull

Trả lời

20

lệnh thừa kế đầu vào tiêu chuẩn của họ từ quá trình bắt đầu họ.. trong trường hợp của bạn, kịch bản của bạn cung cấp đầu vào tiêu chuẩn của nó cho mỗi lệnh đó nó chạy Một ví dụ kịch bản đơn giản:.

#!/bin/bash 
cat > foo.txt 

Piping dữ liệu vào shell script của bạn gây cat để đọc dữ liệu đó, kể từ cat thừa hưởng đầu vào tiêu chuẩn của nó từ tập lệnh của bạn.

$ echo "Hello world" | myscript.sh 
$ cat foo.txt 
Hello world 

Lệnh read được cung cấp bởi vỏ cho việc đọc văn bản từ đầu vào tiêu chuẩn vào một biến vỏ nếu bạn không có một lệnh để đọc hoặc xử lý đầu vào tiêu chuẩn tập lệnh của bạn.

#!/bin/bash 

read foo 
echo "You entered '$foo'" 

$ echo bob | myscript.sh 
You entered 'bob' 
4

Nếu chương trình bên ngoài (mà bạn đang tạo script) đã nhập từ stdin, tập lệnh của bạn không cần phải làm gì cả. Ví dụ, awk đọc từ stdin, do đó, một kịch bản ngắn để đếm số từ trên mỗi dòng:

#!/bin/sh 
awk '{print NF}' 

Sau đó

./myscript.sh <<END 
one 
one two 
one two three 
END 

đầu ra

1 
2 
3 
8

Có một vấn đề ở đây. Nếu bạn chạy kịch bản mà không kiểm tra đầu tiên để đảm bảo có đầu vào trên stdin, sau đó nó sẽ treo cho đến khi một cái gì đó được gõ.

Vì vậy, để giải quyết vấn đề này, bạn có thể kiểm tra để đảm bảo có stdin trước và nếu không, hãy sử dụng đối số dòng lệnh thay vào đó nếu được.

Tạo một kịch bản gọi là "testPipe.sh"

#!/bin/bash 
# Check to see if a pipe exists on stdin. 
if [ -p /dev/stdin ]; then 
     echo "Data was piped to this script!" 
     # If we want to read the input line by line 
     while IFS= read line; do 
       echo "Line: ${line}" 
     done 
     # Or if we want to simply grab all the data, we can simply use cat instead 
     # cat 
else 
     echo "No input was found on stdin, skipping!" 
     # Checking to ensure a filename was specified and that it exists 
     if [ -f "$1" ]; then 
       echo "Filename specified: ${1}" 
       echo "Doing things now.." 
     else 
       echo "No input given!" 
     fi 
fi 

Sau đó, để kiểm tra:

Hãy thêm một số nội dung vào một tập tin test.txt và sau đó ống đầu ra để kịch bản của chúng tôi.

printf "stuff\nmore stuff\n" > test.txt 
cat test.txt | ./testPipe.sh 

Output: Data was piped to this script! Line: stuff Line: more stuff

Bây giờ hãy kiểm tra nếu không cung cấp bất kỳ đầu vào:

./testPipe.sh 

Output: No input was found on stdin, skipping! No input given!

Bây giờ hãy kiểm tra nếu cung cấp tên tệp hợp lệ :

./testPipe.sh test.txt 

Output: No input was found on stdin, skipping! Filename specified: test.txt Doing things now..

Và cuối cùng, chúng ta hãy thử sử dụng một tên tập tin không hợp lệ:

./testPipe.sh invalidFile.txt 

Output: No input was found on stdin, skipping! No input given!

Giải thích: Các chương trình như đọc và mèo sẽ sử dụng stdin nếu nó có sẵn trong trình bao, nếu không chúng sẽ đợi đầu vào.

Tín dụng chuyển đến Mike từ trang này trong câu trả lời của ông cho biết cách kiểm tra đầu vào stdin: https://unix.stackexchange.com/questions/33049/check-if-pipe-is-empty-and-run-a-command-on-the-data-if-it-isnt?newreg=fb5b291531dd4100837b12bc1836456f

Các vấn đề liên quan