2016-06-20 138 views
-1

我有2個腳本,#1和#2。每項工作都可以自行完成。我想逐行讀取15行文件並對其進行處理。腳本#2選擇行。行0被指示爲firstline = 0,lastline = 1。第14行將是firstline = 14,lastline = 15。我從回聲中看到了很好的結果。我想對腳本#1做同樣的事情。無法正確嵌套我的頭。下面的代碼。如何正確嵌套循環

#!/bin/bash 

    # script 1 

    filename=slash 
    firstline=0 
    lastline=1 

    i=0 
    exec <${filename} 
    while read ; do 
     i=$(($i + 1)) 
     if [ "$i" -ge "${firstline}" ] ; then 
     if [ "$i" -gt "${lastline}" ] ; then 
      break 
     else 
      echo "${REPLY}" > slash1 
      fold -w 21 -s slash1 > news1 
      sleep 5 
     fi 
     fi 
    done 


    # script2 

    firstline=(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14) 
    lastline=(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) 

    for ((i=0;i<${#firstline[@]};i++)) 
    do 
     echo ${firstline[$i]} ${lastline[$i]}; 
    done 
+1

一個側面說明,你可以取代'我= $(($ I + 1))'和'((我+ +))'。 – sjsam

+2

事後看來,這是一個[XY問題](http://meta.stackexchange.com/a/66378/248777):使用外部實用程序通過單個循環更好地解決了問題,該循環通過行號 - 不需要_nested_循環。 – mklement0

回答

1

你提的問題是非常不清楚,但也許你只是尋找一些簡單的函數調用:

#!/bin/bash 

script_1() { 

    filename=slash 
    firstline=$1 
    lastline=$2 

    i=0 
    exec <${filename} 
    while read ; do 
     i=$(($i + 1)) 
     if [ "$i" -ge "${firstline}" ] ; then 
     if [ "$i" -gt "${lastline}" ] ; then 
      break 
     else 
      echo "${REPLY}" > slash1 
      fold -w 21 -s slash1 > news1 
      sleep 5 
     fi 
     fi 
    done 
} 


    # script2 

    firstline=(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14) 
    lastline=(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) 

    for ((i=0;i<${#firstline[@]};i++)) 
    do 
     script_1 ${firstline[$i]} ${lastline[$i]}; 
    done 

請注意,讀取文件這種方式的效率非常低,而且有對無疑是更好的方法處理這個,但我想盡量減少你的代碼的變化。

+0

我會嘗試你顯示的代碼。我希望看到15條不同的新聞標題,其中一條新聞1分鐘顯示5秒。 5秒鐘後屏幕空白並顯示下一個標題。消隱發生在Python腳本中。目前只有一個標題已經有效,每5分鐘更新一次。 – donde

1

更新:根據你以後的意見,使用sed提取的每次迭代感興趣的行下面的地道猛砸代碼解決您的問題更加簡單:

注:
- 如果輸入文件在循環迭代之間不會改變,並且輸入文件足夠小(因爲它就在眼前),所以將文件內容緩存到變量中會更有效,如下面原始答案中所示。
- 作爲tripleee在註釋中指出:如果簡單地讀取所述輸入線依次足夠(如由特定行號,反對引出配線然後一個單一的,簡單while read -r line; do ... # fold and output, then sleep ... done < "$filename"足夠

# Determine the input filename. 
filename='slash' 

# Count its number of lines. 
lineCount=$(wc -l < "$filename") 

# Loop over the line numbers of the file. 
for ((lineNum = 1; lineNum <= lineCount; ++lineNum)); do 
    # Use `sed` to extract the line with the line number at hand, 
    # reformat it, and output to the target file. 
    fold -w 21 -s <(sed -n "$lineNum {p;q;}" "$filename") > 'news1' 
    sleep 5 
done 

什麼,我想正在努力實現的簡化版本:

#!/bin/bash 

# Split fields by newlines on input, 
# and separate array items by newlines on output. 
IFS=$'\n' 

# Read all input lines up front, into array ${lines[@]} 
# In terms of your code, you'd use 
# read -d '' -ra lines < "$filename" 
read -d '' -ra lines <<<$'line 1\nline 2\nline 3\nline 4\nline 5\nline 6\nline 7\nline 8\nline 9\nline 10\nline 11\nline 12\nline 13\nline 14\nline 15' 

# Define the arrays specifying the line ranges to select. 
firstline=(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14) 
lastline=(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) 

# Loop over the ranges and select a range of lines in each iteration. 
for ((i=0; i<${#firstline[@]}; i++)); do 
    extractedLines="${lines[*]: ${firstline[i]}: 1 + ${lastline[i]} - ${firstline[i]}}" 
    # Process the extracted lines. 
    # In terms of your code, the `> slash1` and `fold ...` commands would go here. 
    echo "$extractedLines" 
    echo '------' 
done 

注:

  • 填充read -ra數組變量的名稱爲lines; ${lines[@]}是擊語法用於返回所有數組元素作爲單獨的字(${lines[*]}也指所有的元件,但是具有略微不同的語義),並且該語法中的註釋用於示出lines確實是一個陣列變量(注如果你簡單地使用$lines引用變量,你含蓄與指數0,這是一樣的只得到項目:${lines[0]}

  • <<<$'line 1\n...'使用here-string<<<)來讀取AD- hoc 樣品文件(表示爲一個ANSI C-quoted string$'...'))爲了使我的示例代碼自包含的興趣。

    • 正如評論所說,你會從$filename,而不是閱讀:
      read -d '' -ra lines <"$filename"
  • extractedLines="${lines[*]: ${firstline[i]}: 1 + ${lastline[i]} - ${firstline[i]}}"提取感興趣的線路; ${firstline[i]}引用來自數組${firstline[@]}的當前元素(索引i);因爲在bash的數組切片語法
    ${lines[*]: <startIndex>: <elementCount>})的最後一個令牌是元素的計數返回,我們必須執行計算確定計數,這是什麼呢1 + ${lastline[i]} - ${firstline[i]}

    • 藉助於使用"${lines[*]...}"而非"${lines[@]...}"的,所提取的陣列元件由在$IFS的第一個字符,這在我們的情況下是一個新行($'\n')(提取單個線時加入,即沒有按」真的很重要)。
+0

將前面的所有輸入行讀入數組$ {lines [@]}?不確定'@'是什麼意思。讀取行中的$ filename在哪裏? – donde

+0

@donde:查看我的更新;我建議你熟悉一下[Bash中的數組如何工作](https://www.gnu.org/software/bash/manual/html_node/Arrays.html)。 – mklement0

+0

呃,重新讀取輸入文件以提取循環內的單行是一個巨大的反模式。只要閱讀線條。 – tripleee