Bash 如何正确嵌套循环
我有两个剧本#1和#2。每个人都可以自己工作。我想逐行读取一个15行的文件,并对其进行处理。脚本#2选择行。第0行表示为firstline=0,lastline=1。第14行将是firstline=14,lastline=15。我从echo中看到了很好的结果。我想对脚本#1也这样做。我不能正确地进行嵌套。代码如下Bash 如何正确嵌套循环,bash,Bash,我有两个剧本#1和#2。每个人都可以自己工作。我想逐行读取一个15行的文件,并对其进行处理。脚本#2选择行。第0行表示为firstline=0,lastline=1。第14行将是firstline=14,lastline=15。我从echo中看到了很好的结果。我想对脚本#1也这样做。我不能正确地进行嵌套。代码如下 #!/bin/bash # script 1 filename=slash firstline=0 lastline=1 i=0
#!/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
#/bin/bash
#脚本1
文件名=斜杠
第一行=0
最后一行=1
i=0
执行SLA 1
折叠-w 21-s slash1>新闻1
睡眠5
fi
fi
完成
#脚本2
第一行=(01 2 3 4 5 6 7 8 9 10 11 12 14)
最后一行=(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
对于((i=0;i您的问题非常不清楚,但您可能只是在寻找一些简单的函数调用:
#!/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
!/bin/bash
脚本_1(){
文件名=斜杠
第一行=1美元
最后一行=$2
i=0
执行SLA 1
折叠-w 21-s slash1>新闻1
睡眠5
fi
fi
完成
}
#脚本2
第一行=(01 2 3 4 5 6 7 8 9 10 11 12 14)
最后一行=(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
对于((i=0;iUpdate):根据您以后的评论,以下惯用Bash代码使用sed
在每次迭代中提取感兴趣的行,可以更简单地解决您的问题:
注:
-如果输入文件在循环迭代之间不发生变化,并且输入文件足够小(如本例所示),则将文件内容预先缓冲在变量中会更有效,如下面的原始答案所示。
-正如在一篇评论中指出的:如果简单地按顺序读取输入行就足够了(而不是按特定行号提取行),那么在读取-r行时,只需一个简单的;do…#折叠并输出,然后睡眠…done<“$filename”
就足够了。
#确定输入文件名。
filename='slash'
#数一数它的行数。
行数=$(wc-l<“$filename”)
#循环文件的行号。
对于((lineNum=1;lineNum是一个旁注,您可以将i=$($i+1))
替换为((i++))
。事后来看,这是一个问题:使用外部实用程序按行号提取感兴趣的行的单个循环可以更好地解决问题-不需要嵌套循环。我将尝试您显示的代码。我希望看到15个不同的新闻标题,一次一个,在新闻1中显示5秒。5秒后,屏幕空白并显示下一个标题。在Python脚本中会出现空白,甚至更多。只显示一个标题已经有效,每5分钟更新一次。将所有输入行提前读取到数组${lines[@]}?不确定“@”是什么意思。读取行中的$filename在哪里?@donde:请参阅我的更新;我建议您熟悉一下。呃,重新读取输入文件以提取循环中的一行是一个巨大的反模式。只需读取行。@tripleee:我不清楚输入文件是否可以在两次运行之间更改,我们知道输入文件很小,所以我决定在重写答案时不必费心缓冲文件内容。我在答案的顶部添加了一个注释。很遗憾,考虑到这个问题是如何提出的,我担心这对未来的读者没有什么好处。我没有考虑缓冲,只是在阅读时-r线;折叠任何“$线”;睡眠5;完成
# 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