替换一行中的文本,但避免使用某种模式

时间:2017-09-05 19:26:08

标签: regex string sed replace

我正在尝试使用sed替换一行中的文本,但前提是它不在特定模式中。 例如,该行可能是

   bla blab blab \ cite {bla} \ cite [prout] {bla} \ footcite [prout] [hein] {bla} Bla aBla

并且结果必须是(通过用不敏感的情况用KUI替换bla)

  

KUI blab blab \ cite {bla} \ cite [prout] {bla} \ footcite [prout] [hein] {bla} KUI aBla

我不确定sed是否是正确的命令。可以使用其他经典的unix命令。

5 个答案:

答案 0 :(得分:2)

gawk 1级括号A i: 1 A i: 2 A i: 3 A i: 4 A i: 5 B i: 1 B i: 2 B i: 3 B i: 4 B i: 5 的解决方案:

{...}

输出:

awk 'BEGIN{ IGNORECASE=1 }
     {   split($0, a, /\{[^{}]+\}/, seps); 
         for(i=1; i in a; i++) { 
             gsub(/\<bla\>/,"KUI",a[i]); 
             printf "%s%s",a[i],seps[i] 
         } 
         print ""  
     }' file

答案 1 :(得分:1)

sed是简单的s / old / new /,就是这样。你不是简单地做s / old / new /所以你不应该考虑sed。只需使用awk:

$ cat tst.awk
function descend( internalStr) {
    while( ++i <= length($0) ) {
        char = substr($0,i,1)
        internalStr = internalStr char
        if (char == "{") {
            internalStr = internalStr descend()
        }
        else if (char == "}") {
            return internalStr
        }
    }
}
BEGIN { IGNORECASE=1 }
{
    fullStr = externalStr = ""
    i = 0
    while( ++i <= length($0) ) {
        char = substr($0,i,1)
        externalStr = externalStr char
        if (char == "{") {
            gsub(/\<bla\>/,"KUI",externalStr)
            fullStr = fullStr externalStr descend()
            externalStr = ""
        }
    }
    gsub(/\<bla\>/,"KUI",externalStr)
    print fullStr externalStr
}

$ cat file
bla blab blab \cite{bla} \cite[prout]{bla} \footcite[prout][hein]{ bla } Bla aBla
bla \tag1{ bla \tag2{ bla } bla } bla

$ gawk -f tst.awk file
KUI blab blab \cite{bla} \cite[prout]{bla} \footcite[prout][hein]{ bla } KUI aBla
KUI \tag1{ bla \tag2{ bla } bla } KUI

以上使用GNU awk进行字边界和IGNORECASE。对其他人的需求很容易与其他问题一起解决。

请注意,它甚至适用于嵌套标记(第二个输入/输出行)。

答案 2 :(得分:0)

执行:

sed -e 's/\<[bB]la\>/KUI/g' yourFile

其中:

\<bla\> 

指定搜索与字符串'bla'完全匹配的单词。 \<用于指定单词的开头。在这种情况下,单词必须以b或B开头。\>指定单词的结尾。在这种情况下,它必须以a结尾。在'b'('B')和'a'之间,必须只有一个'l'。

<强>更新 我注意到sed没有很好地阅读字符'{'和'}',所以它也考虑了一个单词{bla}并将其翻译成{KUI}。 解决方法如下:

sed -e 's/{/opened/g' yourFile > newFile
sed -e 's/}/closed/g' newFile1 > yourFile

sed -e 's/\<[bB]la\>/KUI/g' yourFile > newFile

sed -e 's/opened/{/g' newFile > yourFile
sed -e 's/closed/}/g' yourFile > newFile

它不是那么优雅,但它有效。

希望有所帮助

答案 3 :(得分:0)

第一个变体 - 使用嵌套大括号。

awk -F '' '
    function buf_sub() {
        gsub(/\ybla\y/, "KUI", buffer);
        string = string buffer;
        buffer = "";
    }
    BEGIN {
        IGNORECASE = 1;
    }
    {
        string = "";
        buffer = "";
        for(i = 1; i <= NF; i++) {
            if(cnt) 
                string = string $i; 
             else 
                buffer = buffer $i;

            if($i == "{") {
                cnt++;
                buf_sub();
            } 
            if($i == "}") 
                cnt--;  
        }
        buf_sub();
        print string;
    }
' input.txt

<强>输入

bla blab blab \cite{bla} \cite[prout]{bla} \footcite[prout][hein]{ bla } Bla aBla
blab bla blab \cite{bla} \cite[prout]{bla} \footcite[prout][hein]{ bla } aBla Bla
bla \tag1{ bla \tag2{ bla } bla } bla 

<强>输出

KUI blab blab \cite{bla} \cite[prout]{bla} \footcite[prout][hein]{ bla } KUI aBla
blab KUI blab \cite{bla} \cite[prout]{bla} \footcite[prout][hein]{ bla } aBla KUI
KUI \tag1{ bla \tag2{ bla } bla } KUI

第二个变体 - 不处理大括号嵌套。

sed -r 's/(\\[^}]*})/\n@#\1\n@#/g' input.txt |
sed '/\\/! s/\bbla\b/KUI/gI;' |
sed ':lab; N; $!b lab; s/\n@#//g;'

<强>输入

bla blab blab \cite{bla} \cite[prout]{bla} \footcite[prout][hein]{ bla } Bla aBla
blab bla blab \cite{bla} \cite[prout]{bla} \footcite[prout][hein]{ bla } aBla Bla

<强>输出

KUI blab blab \cite{bla} \cite[prout]{bla} \footcite[prout][hein]{ bla } KUI aBla
blab KUI blab \cite{bla} \cite[prout]{bla} \footcite[prout][hein]{ bla } aBla KUI

答案 4 :(得分:0)

使用perl的解决方案:

perl -lpe 's/(\\footcite([^}]*)|\\cite([^}]*))(*SKIP)(*FAIL)|\bbla\b/KUI/ig' file

替换过程中将避免使用\footcite\cite命令。