在匹配之前打印第10行或在文件列表中匹配后打印第10行,在BASH中将最后一行循环到第一行?

时间:2014-05-24 00:49:47

标签: bash

我在words.txt

中有一个包含已排序和唯一项目的长列表的文件
apple
banana
cat
cattle
celery
cucumber
eagle
eel
fish
lion
llama
mountain lion
ostrich
pear
tomato
zebra

我需要在搜索字词之前打印10行或在搜索字词后出现10行的项目。如果它到达文件的末尾,它应该从文件的第一行继续计数以找到正确的匹配。例如,如果我搜索“鱼”,之前的10行将返回“番茄”,之后的10行将返回“cat”。

这是我到目前为止所尝试的:

#!/bin/bash

count=`wc -l words.txt`

line="$(grep -n ^fish$ words.txt | cut -f1,1 -d:)"

echo $line

tenbefore=`expr $line - 10`
tenbefore="$(head -n "$tenbefore" words.txt)"

if [ "$tenbefore" < 1 ]
then
    tenbefore=`expr $count + $tenbefore`
    tenbefore="$(head -n "$tenbefore" words.txt)"
fi

echo $tenbefore

tenafter=`expr $line - 10`
tenafter="$(head -n "$tenafter" words.txt)"

if [ "$tenafter" > "$count" ]
then
    tenafter=`expr $tenafter - $count`
    tenafter="$(head -n "$tenafter" words.txt)"
fi

echo $tenafter

如何在匹配之前打印第10行或在匹配之后打印第10行,但是在第10行之前是第一行之前或之后第10行的情况下,将文件末尾循环到开头在最后一行之后,在BASH?

1 个答案:

答案 0 :(得分:2)

如果您被允许将整个内容读入内存,我会这样做。

#!/bin/bash
IFS=$'\n' read -r -a words -d '' <words.txt
let len=${#words[@]}
for (( i=0; i<len; ++i )); do
  if [ "${words[i]}" = fish ]; then
    echo "${words[(i+len-10)%len]}" # ten before
    echo "${words[(i+10)%len]}" # ten after
    exit 0
  fi
done
exit 1 # not found

您也可以通过跟踪10个最近的行以及文件的前10行来进行操作,只需稍微调整一下即可。如果你正在处理巨型文件,这就变得有价值/必要,但除此之外,上面的简单解决方案更容易一些。