返回所有匹配项的上一行

返回所有匹配项的上一行

我需要获取程序的多行输出,匹配一个字符串,并返回所有匹配的前一行。

程序输出的示例:

$ jack_lsp -p
firewire_pcm:analog-1_out
        properties: input,physical,terminal,
firewire_pcm:analog-2_out
        properties: input,physical,terminal,
firewire_pcm:analog-1_in
        properties: output,physical,terminal,
firewire_pcm:analog-2_in
        properties: output,physical,terminal,
$

我需要匹配,例如“输入”,并返回所有匹配的上一行。因此,在示例中,预期输出为:

firewire_pcm:analog-1_out
firewire_pcm:analog-2_out

这是我所拥有的,但它只返回第一个匹配项:

$ jack_lsp -p | grep -B1 input | head -1
firewire_pcm:analog-1_out
$

我究竟做错了什么?

答案1

这是您正在尝试的命令:

jack_lsp -p | grep -B1 input | head -1

这样做的问题是,head -1将返回第一行全部的通过管道传送给它的数据流。

尝试使用以下awk命令:

jack_lsp -p | awk '/input/{print previous_line}{previous_line=$0}'

它将打印出包含字符串“input”的每一行之前的行。这是示例数据的结果:

user@host:~$ cat <<HEREDOC | awk '/input/{print previous_line}{previous_line=$0}'
firewire_pcm:analog-1_out
        properties: input,physical,terminal,
firewire_pcm:analog-2_out
        properties: input,physical,terminal,
firewire_pcm:analog-1_in
        properties: output,physical,terminal,
firewire_pcm:analog-2_in
        properties: output,physical,terminal,
HEREDOC

firewire_pcm:analog-1_out
firewire_pcm:analog-2_out

有关此awk方法的更多信息,请参阅以下帖子:

您可以使用以下方法完成同样的事情sed

<!-- language: bash -->

jack_lsp -p |sed -n '/input/{x;p;d;}; x'

有关此sed方法的更多信息,请参阅以下帖子:

在您的特定情况下,您匹配的字符串(即“输入”)看起来没有出现在前一行中,因此您也可以使用以下方法过滤掉这些行grep,即:

jack_lsp -p | grep -B1 'input' | grep -v 'input

awk您还可以通过补充一些 shell 脚本来获得与上述方法相同的结果grep,尽管结果并不那么紧凑:

jack_lsp -p | (
    unset previous_line;
    while read line; do
        if grep -q input <<< "${line}" && [[ -n "${previous_line}" ]]; then
            echo "${previous_line}";
        fi;
        previous_line="${line}";
    done
)

答案2

使用 gnu-grep(适用于所有平台并在大多数平台上默认安装)我们可以:

jack_lsp -p | grep -zPo '.*\n(?=.*input)'

在哪里

  • -z表示用 null 分隔的“行”(事实上,它最终会占用整个文件)——具有多行模式
  • -P类似 Perl 的正则表达式方言——具有先行功能
  • '.*\n(?=.*input)'由包含“input”的另一行向前查找的行

答案3

为什么不简单一点,并使用ex具有反向寻址功能的 :

printf '%s\n' 'g/input/-p' | ex file.txt

对于在管道中而不是在文件中运行它,它看起来有点棘手,但工作原理相同:

jack_lsp -p | ex -s /dev/stdin -c $'g/input/-p\nq'

答案4

这个片段:

# Utility functions: print-as-echo, print-line-with-visual-space.
pe() { for _i;do printf "%s" "$_i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }
pl " Input data file $FILE:"
head $FILE

pl " Expected output:"
cat $E

pl " Results:"
rm -f f1
ed --silent $FILE > f1 <<EOF
g/input/.-1p
q
EOF
head f1

产生:

-----
 Input data file data1:
firewire_pcm:analog-1_out
        properties: input,physical,terminal,
firewire_pcm:analog-2_out
        properties: input,physical,terminal,
firewire_pcm:analog-1_in
        properties: output,physical,terminal,
firewire_pcm:analog-2_in
        properties: output,physical,terminal,

-----
 Expected output:
firewire_pcm:analog-1_out
firewire_pcm:analog-2_out

-----
 Results:
firewire_pcm:analog-1_out
firewire_pcm:analog-2_out

ed 命令很简单:1)找到与“输入”匹配的行2)打印上一行。

在如下系统上运行:

OS, ker|rel, machine: Linux, 3.16.0-4-amd64, x86_64
Distribution        : Debian 8.9 (jessie) 
ed GNU Ed 1.10

最美好的祝愿...干杯,drl

相关内容