使用bash读取文本文件中的行的子集

时间:2021-07-23 15:46:14

I have a file

我有一个文件

line a - this is line a
line b - this is line b
line c - this is line c
line d - this is line d
line e - this is line e

The question is: How can I output the lines starting from "line b" till "line d" using bash commands? I mean, to obtain:

问题是:如何使用bash命令输出从“line b”开始直到“line d”的行?我的意思是,获得:

"line b - this is line b
 line c - this is line c
 line d - this is line d"

6 个解决方案

#1


sed -n '/line b/,/line d/p' file

#2


for your set of sample data:

对于您的样本数据集:

awk '/line b/,/line d/' file

Or

awk '/line d/{f=0;print}/line b/{f=1}f' file

#3


If by bash, you mean actually bash alone, I can't help you. You really should be using the right tools for the job. If you mean standard UNIX utilities that you can call from bash, I would be using awk for that.

如果用bash,你的意思实际上是单独打击,我无法帮助你。你真的应该使用正确的工具来完成工作。如果你的意思是你可以从bash调用的标准UNIX实用程序,我将使用awk。

echo 'line a - this is line a
line b - this is line b
line c - this is line c
line d - this is line d
line e - this is line e' | awk '
    BEGIN {e=0}
    /^line b/ {e=1}
    /^line d/ {if (e==1) {print;exit}}
    {if (e==1) print}
'

This outputs:

line b - this is line b
line c - this is line c
line d - this is line d

The way it works is simple.

它的工作方式很简单。

  • e is the echo flag, initially set to false (0).
  • e是echo标志,最初设置为false(0)。

  • when you find line b, set echo to true (1) - don't print yet. That will be handled by the last bullet point below.
  • 当你找到第b行时,将echo设置为true(1) - 不要打印。这将由下面的最后一个要点处理。

  • when you find line d and echo is on, print it and exit.
  • 当你找到d行并且回显打开时,打印并退出。

  • when echo is on, print the line (this includes line b).
  • 当echo打开时,打印该行(包括行b)。

I've made an assumption here that you don't want to exit on a line d unless you're already echoing. If that's wrong, move the exit outside of the if statement for line d:

我在这里做了一个假设,除非你已经回应,否则你不想在第d行退出。如果这是错误的,请将出口移到行d的if语句之外:

    /^line d/ {if (e==1) print;exit}

Then, if you get a line d before your line b, it will just exit without echoing anything.

然后,如果你在你的第b行之前得到一行,它就会退出而不会回响任何东西。

The "/^line X/"-type clauses can be made very powerful to match pretty well anything you can throw at it.

“/ ^ line X /” - 类型子句可以非常强大,可以很好地匹配你可以抛出的任何东西。

#4


Your example is not enough to infer what you want in the general case, but assuming you want to remove the first and last line, you can simply use

您的示例不足以在一般情况下推断出您想要的内容,但假设您要删除第一行和最后一行,则可以使用

tail -n+2 $filename | head -n-1

Here tail -n+2 prints all the lines starting from the second, and head -n-1 prints all the lines except the last.

这里tail -n + 2打印从第二行开始的所有行,head -n-1打印除了last之外的所有行。

#5


You can do it using bash alone, though I agree with Pax that using other tools is probably a better solution. Here's a bash-only solution:

你可以单独使用bash来做,虽然我同意Pax使用其他工具可能是一个更好的解决方案。这是一个仅限bash的解决方案:

while read line
do
    t=${line#line b}
    if test "$t" != "$line"
    then
        echo $line
        while read line
        do
            echo $line
            t=${line#line d}
            if test "$t" != "$line"
            then
                exit 0
            fi
        done
    fi
done

#6


Another approach which depends on what you mean:

另一种方法取决于你的意思:

pcregrep -m 'line b - this is line b
 line c - this is line c
 line d - this is line d' file

#1


sed -n '/line b/,/line d/p' file

#2


for your set of sample data:

对于您的样本数据集:

awk '/line b/,/line d/' file

Or

awk '/line d/{f=0;print}/line b/{f=1}f' file

#3


If by bash, you mean actually bash alone, I can't help you. You really should be using the right tools for the job. If you mean standard UNIX utilities that you can call from bash, I would be using awk for that.

如果用bash,你的意思实际上是单独打击,我无法帮助你。你真的应该使用正确的工具来完成工作。如果你的意思是你可以从bash调用的标准UNIX实用程序,我将使用awk。

echo 'line a - this is line a
line b - this is line b
line c - this is line c
line d - this is line d
line e - this is line e' | awk '
    BEGIN {e=0}
    /^line b/ {e=1}
    /^line d/ {if (e==1) {print;exit}}
    {if (e==1) print}
'

This outputs:

line b - this is line b
line c - this is line c
line d - this is line d

The way it works is simple.

它的工作方式很简单。

  • e is the echo flag, initially set to false (0).
  • e是echo标志,最初设置为false(0)。

  • when you find line b, set echo to true (1) - don't print yet. That will be handled by the last bullet point below.
  • 当你找到第b行时,将echo设置为true(1) - 不要打印。这将由下面的最后一个要点处理。

  • when you find line d and echo is on, print it and exit.
  • 当你找到d行并且回显打开时,打印并退出。

  • when echo is on, print the line (this includes line b).
  • 当echo打开时,打印该行(包括行b)。

I've made an assumption here that you don't want to exit on a line d unless you're already echoing. If that's wrong, move the exit outside of the if statement for line d:

我在这里做了一个假设,除非你已经回应,否则你不想在第d行退出。如果这是错误的,请将出口移到行d的if语句之外:

    /^line d/ {if (e==1) print;exit}

Then, if you get a line d before your line b, it will just exit without echoing anything.

然后,如果你在你的第b行之前得到一行,它就会退出而不会回响任何东西。

The "/^line X/"-type clauses can be made very powerful to match pretty well anything you can throw at it.

“/ ^ line X /” - 类型子句可以非常强大,可以很好地匹配你可以抛出的任何东西。

#4


Your example is not enough to infer what you want in the general case, but assuming you want to remove the first and last line, you can simply use

您的示例不足以在一般情况下推断出您想要的内容,但假设您要删除第一行和最后一行,则可以使用

tail -n+2 $filename | head -n-1

Here tail -n+2 prints all the lines starting from the second, and head -n-1 prints all the lines except the last.

这里tail -n + 2打印从第二行开始的所有行,head -n-1打印除了last之外的所有行。

#5


You can do it using bash alone, though I agree with Pax that using other tools is probably a better solution. Here's a bash-only solution:

你可以单独使用bash来做,虽然我同意Pax使用其他工具可能是一个更好的解决方案。这是一个仅限bash的解决方案:

while read line
do
    t=${line#line b}
    if test "$t" != "$line"
    then
        echo $line
        while read line
        do
            echo $line
            t=${line#line d}
            if test "$t" != "$line"
            then
                exit 0
            fi
        done
    fi
done

#6


Another approach which depends on what you mean:

另一种方法取决于你的意思:

pcregrep -m 'line b - this is line b
 line c - this is line c
 line d - this is line d' file