在文件中首次出现特定字符串之前删除所有行

时间:2016-03-13 02:31:44

标签: bash awk sed

基本上我有一个像:

这样的文件
junk
morejunk
somestring
bats
car
somestring
bats
car
somestring
bats
car

我希望在第一次出现junk之前删除所有somestring,以便文件看起来像

somestring
bats
car
somestring
bats
car
somestring
bats
car

我按照this question的建议使用sed -i '0,/somestring/,d' file.txt但是当我想将该行保留为第一行时,它会删除第一次出现somestring的行。

5 个答案:

答案 0 :(得分:11)

使用sed,您可以使用:

sed -i '/somestring/,$!d' file

替换表达式的说明:

  

,匹配从第一个开始的行   地址匹配,并持续到第二场比赛   (包括性)。

     

$匹配最后一个输入文件的最后一行,   或-i或-s选项时每个文件的最后一行   指定。

     

!如果字符在地址范围之后,则只有行   将选择与地址范围不匹配的。

     

d删除模式空间;立即开始下一个周期。   

结果:

$ sed -i '/somestring/,$!d' file
somestring
bats
car
somestring
bats
car
somestring
bats
car

答案 1 :(得分:3)

$ sed -n '/somestring/,$p' infile
somestring
bats
car
somestring
bats
car
somestring
bats
car

该命令禁止使用-n进行打印,然后对于地址范围/somestring/,$,即从somestring到最后一行,执行p命令以打印线。

答案 2 :(得分:1)

以下是使用awk的方法:

awk '/somestring/ { f = 1 } f' file

当模式匹配时,将f设置为true。当f成立时,打印每一行。

另一个选择,稍微有点神秘:

awk 'f += /somestring/' file
当模式匹配时,{p> f增加1,或者0增加#include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <math.h> int add(int input1, char operand, int input2); int subtract(int input1, char operand, int input2); int mod(int input1, char operand, int input2); int multiply(int input1, char operand, int input2); int divide(int input1, char operand, int input2); char cont(void); int main() { int answer = 0; int ch = 0; int input1 = 0; char operand = 0; int input2 = 0; int function = 0; char flag; do { input1 = 0, input2 = 0, operand = 0; printf("\nPlease enter a calculation to be made.\n"); while (((ch = getchar()) != ' ') && (ch != EOF) && (ch != '\n')){ if (ch == '-') { printf("\nError: no negatives allowed.\n"); } else if (!isdigit(ch)){ printf("\nError: number not inputted (first number).\n"); } else { input1 = (input1 * 10) + (ch - '0'); } } while (((ch = getchar()) != ' ') && (ch != EOF) && (ch != '\n')){ switch (ch){ case '+': operand = '+'; break; case '-': operand = '-'; break; case '%': operand = '%'; break; case '*': operand = '*'; break; case '/': operand = '/'; break; default: printf("Error: input is not one of the allowed operands."); break; } } while (((ch = getchar()) != ' ') && (ch != '\n')){ if (ch == '-') { printf("\nError: no negatives allowed.\n"); } else if (!isdigit(ch)){ printf("\nError: number not inputted (second number).\n"); } else { input2 = (input2 * 10) + (ch - '0'); } } printf("%d", input1); putchar(' '); printf("%c", operand); putchar(' '); printf("%d", input2); putchar(' '); putchar('='); putchar(' '); if (operand == '+'){ answer = add(input1, operand, input2); printf("%d", answer); } else if (operand == '-'){ answer = subtract(input1, operand, input2); printf("%d", answer); } else if (operand == '%'){ answer = mod(input1, operand, input2); printf("%d", answer); } else if (operand == '*'){ answer = multiply(input1, operand, input2); printf("%d", answer); } else if (operand == '/'){ answer = divide(input1, operand, input2); printf("%d", answer); } flag = cont(); } while (flag == 'y' || flag == 'Y'); return 0; } int add(int input1, char operand, int input2){ return input1 + input2; } int subtract(int input1, char operand, int input2){ return input1 - input2; } int mod(int input1, char operand, int input2){ return input1 % input2; } int multiply(int input1, char operand, int input2){ return input1 * input2; } int divide(int input1, char operand, int input2){ return input1 / input2; } char cont() { char flag; printf("\nDo you want to process another calculation (y/n)? "); scanf("%c%*c", &flag); return flag; } 。一旦一条线与图案匹配,表达式就变为真,所以每一行都被打印出来。

答案 3 :(得分:1)

另一个惯用的awk解决方案(以及最少的击键次数)

$ awk '/somestring/,0' file   

somestring
bats
car
somestring
bats
car
somestring
bats
car

答案 4 :(得分:0)

与Echo和GNU Sed连接

你有大部分使用GNU sed的解决方案,它允许你在范围模式中使用行号和正则表达式。您真正需要做的就是将您正在使用的字符串作为结束模式添加到结果输出中。

例如:

$ str='somestring'; echo -e "${str}\n$(sed "0,/${str}/d" /tmp/corpus)"
somestring
bats
car
somestring
bats
car
somestring
bats
car

基本上,您将模式分配给 str ,然后在echo语句和sed表达式中重用它。如果遇到与变量插值相关的引用问题,只需在echo和sed命令中用固定字符串替换 str 变量。但是,与发布的语料库一致。