使用sed

时间:2017-10-04 22:02:37

标签: linux bash sed

我们说我有一个名为original.txt的文件,内容如下:

红色
蓝色

食品

灰色

此外,我还有一个名为new.txt的文件,其中包含以下内容:

绿色


紫色

现在我想编写一个脚本,用blue替换grayoriginal.txtnew.txt之间的行,其内容为newtext="new.txt" sed -i "/blue/,/gray/{ r $newtext d }" original.txt ,因此它给出了我的结果:< / p>

红色
蓝色
绿色

黄色

灰色

我为此目的编写了这段代码(新文件的名称并不总是相同,因此它存储在变量中):

red
green
black
yellow
purplegreen
black
yellow
purplegreen
black
yellow
purplegreen
black
yellow
purplegreen
black
yellow
purplewhite

然而,在运行它时,我得到了这个废话:

#include <stdio.h>
#include <stdlib.h>


// Type Definitions

// These are the type definitions that can be used to check for type
// They need to be unique so that only types starting with these
// prefixes will be presumed to be of the type specified.
typedef enum type {
    TYPE_StateRequester = 0x10f3ccd3,
    TYPE_OtherThing = 0x09331c8c
} type;


// State Requester Definitions & Functions

typedef int state_requester_f(void* request_parameters);

// Since we want to check the "type" of a function reference,
// we need to wrap it in a struct along with it's type code.
struct state_requester_t {
    int type;
    state_requester_f* call;
} typedef state_requester_t;

state_requester_t new_state_requester(state_requester_f* call) {
    state_requester_t sr;
    sr.type = TYPE_StateRequester;
    sr.call = call;
    return sr;
}

// This function will check if data is of type StateRequester
// 
// If the data sent to this function is not of the length
// nessecary for the state_requester type, - OR - 
// it's type property is not equal to the StateRequester type
// then we will presume that this data is NOT of type StateRequester
uint8_t is_state_requester(void* data, size_t len) {
    return len == sizeof(state_requester_t) && 
           ((state_requester_t*)data)->type == TYPE_StateRequester;
}


// Testing functions

int test_caller(void* data) {
    printf("Got to the test_caller function.\n");

    return 0;
}

int main(int agc, char *argv[]) {

    // Create an actual state_requester_t definitiion
    state_requester_t sr = new_state_requester(&test_caller);

    // Test to see if it's validated as a state_requester_t
    if (is_state_requester(&sr, sizeof(state_requester_t))) {
        printf("Yes, variable 'sr' is presumadely of type state_requester_t\n");
        sr.call(NULL);
    } else {
        printf("No, variable 'sr' is not of type state_requester_t\n");
    }

    // Create a phony state_requester_t definition,
    // but keep it the same length as a regular
    // state_requester_t
    void* a = malloc(sizeof(state_requester_t));

    // Test to see if it's validated as a state_requester_t
    if (is_state_requester(a, sizeof(state_requester_t))) {
        printf("Yes, variable 'a' is presumadely of type state_requester_t\n");
    } else {
        printf("No, variable 'a' is not of type state_requester_t\n");
    }

    free(a);

    // Create a phony state_requester_t with an improper length
    void* b = malloc(5);

    // Test to see if it's validated as a state_requester_t 
    if (is_state_requester(b, sizeof(state_requester_t))) {
        printf("Yes, variable 'b' is presumadely of type state_requester_t\n");
    } else {
        printf("No, variable 'b' is not of type state_requester_t\n");
    }    

    free(b);

    return 0;
}

我做错了什么?

3 个答案:

答案 0 :(得分:6)

这可能适合你(GNU sed):

sed '/blue/,/gray/!b;//!d;/blue/r file2' file1

对于bluegray之间的行范围,删除与范围中的第一行或最后一行不匹配的行,并读取要在范围的最后一行之前插入的行

编辑:

第一个sed命令/blue/,/grey/!b匹配一系列行,即包含blue的行与包含gray的行之间的行。 !b部分意味着如果这些行不在该范围内,则会中断sed命令,即不对这些行进行任何进一步的sed处理,只需正常打印。

以下sed命令仅会影响bluegray之间范围内的行。

第二个命令//!d表示:删除那些与范围的开头/结尾不匹配的行,即bluegray//使用先前/.../命令的正则表达式。注:删除命令终止该行的任何进一步的sed处理。

以下sed命令只会影响包含bluegray的行。

第三个命令匹配包含blue的行,并从file2读取行。

N.B。包含bluegrey的行将由sed自然处理并在下一行读入模式空间之前打印,而不是bluegray之间的行。< / p>

替代方案:

sed '/blue/,/gray/!b;//!d;/gray/e cat file2' file1

另一个:

sed -ne '/blue/{p;r file2' -e ':a;n;/gray/!ba};p' file1

答案 1 :(得分:2)

sed适用于s / old / new /,全部。对于其他任何你应该使用awk:

$ awk 'NR==FNR{new = new $0 ORS; next} /gray/{f=0} !f{print} /blue/{printf "%s",new; f=1}' new.txt original.txt
red
blue
green
black
yellow
purple
gray
white

以上内容适用于任何UNIX机器上的任何shell中的任何awk,并且不需要重复任何开始/结束正则表达式。非常重要的是,它也可以简单地建立在你现在或将来做任何其他事情的基础上!例如,为了能够指定开始和结束的正则表达式,因为参数将是:

$ awk -v beg='blue' -v end='gray' 'NR==FNR{new = new $0 ORS; next} $0~end{f=0} !f{print} $0~beg{printf "%s",new; f=1}' new.txt original.txt

广告然后您可以更改它们:

$ awk -v beg='water' -v end='tree' 'NR==FNR{new = new $0 ORS; next} $0~end{f=0} !f{print} $0~beg{printf "%s",new; f=1}' new.txt original.txt
red
blue
water
green
black
yellow
purple
tree
gray
white

您可能想要做的任何事情只是使用相同构造的简单重新排列,例如不打印起始行:

$ awk -v beg='blue' -v end='gray' 'NR==FNR{new = new $0 ORS; next} $0~end{f=0} $0~beg{printf "%s",new; f=1} !f{print}' new.txt original.txt
red
green
black
yellow
purple
gray
white

和类似的调整,不打印结束行或不打印或做任何其他....

答案 2 :(得分:0)

我看到您要求sed帮助,但是ex以更直接的方式处理此用例。 这可能对您有用(在Shell脚本中):

ex original.txt << EOF_EX
/blue/+1,/gray/-1 d
r new.txt
w edited.txt
q!
EOF_EX

上面的代码打开了original.txt文件进行编辑,删除了从蓝到蓝,从一到蓝的行范围,读取了文件new.txt,并写出了edited.txt文件。

结果:

$ cat edited.txt
red
blue
gray
green
black
yellow
purple
white

或者,您也可以将“ w edited.txt”替换为“ wq”,并将更改保存在original.txt文件中。

此外,请注意该范围内的+1和-1语法,这可能非常方便。 例如,如果您还想删除范围边界模式“蓝色”和“灰色”,则可以删除+1和-1,这意味着删除范围,包括范围边界模式。