在搜索特定行后如何输出文件的上一行?

时间:2011-01-28 14:15:49

标签: unix scripting

如何在搜索一行后获取文件的上一行?

示例:有一个名为fore.dat的文件包含:

:Server:APBS

        :Max Blocking queue:20

:Transport:000

        :Server:APBS

        :Max Transactions:10

        :MaxConnections:1

:Transport:001

        :Server:APBS

        :Max Transactions:10

        :MaxConnections:1

:Transport:005
        :Server:BIT

        :Max Transactions:10

        :Max Connections:1

:Transport:004

        :Server:APBS

        :Max Transactions:44440

        :Max Connections:1

:Transport:002

        :Server:BET

        :Max Transactions:10

        :Max Connections:1

:Transport:003

        :Server:APBS

        :Max Transactions:50

        :Max Connections:1

我想将包含服务器名称的传输号码打印为APBS。 即;输出为:

:Transport:000

:Transport:001

:Transport:004

:Transport:003

5 个答案:

答案 0 :(得分:1)

这看起来像是awk的工作,它甚至可以在你没有gawk的AIX上工作......

% awk -F':' '
/^:Transport:/ {
    transport = $0
}

NF == 3 && $2 == "Server" && $3 == "APBS" {
    printf "%s\n\n", transport
}

' fore.dat


:Transport:000

:Transport:001

:Transport:004

:Transport:003

说明:

  • 致电awk
  • 将':'视为字段分隔符。
  • 对于以':Transport:'开头的所有行,请将整行保存为transport
  • 对于包含三个字段的任何行,其中第二个是“Server”,第三个是“APBS”,请打印最后存储的transport值,后跟一对换行符。
  • 使用fore.dat作为输入文件。

有许多不同的方法可以做到这一点。这只是一个。

答案 1 :(得分:0)

您需要详细了解您正在使用的语言。

这是我要做的。我会扫描文件的每一行。我会将'last read'行放入缓冲区。如果下一行包含您要查找的内容,请输出存储在缓冲区中的行。

答案 2 :(得分:0)

grep -B1 APBS <filename>返回包含APBS的行及其正上方的行。

grep -B1 APBS <filename>| grep Transport会返回包含传输号码的行。

答案 3 :(得分:0)

在读取一行(actual_line)之前,将您拥有的行存储在临时变量(previous_line)中。当你找到你需要的那个(actual_line是你要找的那个)时,只需返回前一个(previous_line)

答案 4 :(得分:0)

鉴于您没有使用GNU grep并假设您无法安装它,那么您必须依赖其他工具。这是一个我称之为'sgrep'的脚本,正如您从日期信息中看到的那样,它已经相当陈旧,但是是为Xenix,SunOS(早于Solaris),HP-UX,AIX以及其他一大堆已久的而编写的。 Unix的变种。它可以相当彻底地完成工作 - 它比您目前需要的更全面。

:   "$Id: sgrep.sh,v 1.3 1989/05/12 10:24:14 john Exp $"
#
#   Special grep
#   Finds a pattern and prints lines either side of the pattern
#   Line numbers are always produced by ed (substitute for grep),
#   which allows us to eliminate duplicate lines cleanly.  If the
#   user did not ask for numbers, these are then stripped out.
#
#   BUG: if the pattern occurs in in the first line or two and
#   the number of lines to go back is larger than the line number,
#   it fails dismally.

set -- `getopt "f:b:n" "$@"`

case $# in
0)  echo "Usage: $0 [-n] [-f x] [-b y] pattern [files]" >&2
    exit 1;;
esac

number="'s/^\\([0-9][0-9]*\\)   /\\1:/'"
filename="'s%^%%'"      # No-op for sed

f=3
b=3
nflag=no
while [ $# -gt 0 ]
do
    case $1 in
    -f) f=$2; shift 2;;
    -b) b=$2; shift 2;;
    -n) nflag=yes; shift;;
    --) shift; break;;
    *)  echo "Unknown option $1" >&2
        exit 1;;
    esac
done
pattern="${1:?'No pattern'}"
shift

case $# in
0)  tmp=${TMPDIR:-/tmp}/`basename $0`.$$
    trap "rm -f $tmp ; exit 1" 0
    cat - >$tmp
    set -- $tmp
    sort="sort -t: -u +0n -1"
    ;;
*)  filename="'s%^%'\$file:%"
    sort="sort -t: -u +1n -2"
    ;;
esac

for file in $*
do
    {
    ed - $file <<-!
    g/$pattern/.-${b},.+${f}n
    !
    } |
    eval sed -e "$number" -e "$filename" \| $sort |
    case $nflag in
    yes)    cat -;;
    no)     sed 's/[0-9][0-9]*://';;
    esac
done

rm -f $tmp
trap 0
exit 0

我不得不把它从我保存古老软件的化石床中挖出来。我有一个基本相同的Perl脚本;我不经常使用,因为我通常安装了GNU grep。