如何根据匹配模式用另一个文件中的行替换文本文件中的行?

时间:2017-10-18 15:23:31

标签: shell awk sed

我想基于匹配模式,用另一个文件中的行替换文件中的某些行。 我想替换以" rolOccupant"开头的每一行。找到后 "#SBD_ING_USER"包含文件x

中内容的空行

档案x

roleOccupant: uid1
roleOccupant: uid2
roleOccupant: uid45
roleOccupant: uid80

输入文件

# SDB_ING_USER
objectClass: organizationalRole
objectClass: top
cn: SDB_ING_USER
description: SDB Ing User Role
roleOccupant: uid1
roleOccupant: uid7
roleOccupant: uid67

# SDB_REGISTERY_USER: 
objectClass: organizationalRole
objectClass: top
cn: SDB_REGISTRY_USER
description: SDB Registry Admin Role
roleOccupant: uid2
roleOccupant: uid34
roleOccupant: uid15

OUTPUT文件

# SDB_ING_USER
objectClass: organizationalRole
objectClass: top
cn: SDB_ING_USER
description: SDB Ing User Role
roleOccupant: uid1
roleOccupant: uid2
roleOccupant: uid45
roleOccupant: uid80

# SDB_REGISTERY_USER: 
objectClass: organizationalRole
objectClass: top
cn: SDB_REGISTRY_USER
description: SDB Registry Admin Role
roleOccupant: uid2
roleOccupant: uid34
roleOccupant: uid15

4 个答案:

答案 0 :(得分:2)

awk 单线

 awk -v RS= -v ORS='\n\n' 'NR==FNR{a=$0;next} /SDB_ING_USER/{sub(/roleOccupant.*/,""); $0=$0 a} 1' fileX file 

-v RS=将空行设置为记录分隔符

FNR==NR{a=a$0; next}:这会将您的File X内容存储在变量a

/# SDB_ING_USER/ {gsub(/roleOccupant.*/,a ORS)}:迭代Input file if记录包含# SDB_ING_USER,然后将所有行从roleOccupant替换为记录结尾a ORS换句话说a "\n"

输出

# SDB_ING_USER
objectClass: organizationalRole
objectClass: top
cn: SDB_ING_USER
description: SDB Ing User Role
roleOccupant: uid1
roleOccupant: uid2
roleOccupant: uid45
roleOccupant: uid80

# SDB_REGISTERY_USER:
objectClass: organizationalRole
objectClass: top
cn: SDB_REGISTRY_USER
description: SDB Registry Admin Role
roleOccupant: uid2
roleOccupant: uid34
roleOccupant: uid15

答案 1 :(得分:0)

使用awk

<强>一衬垫:

awk 'FNR==NR{r=(r!=""?r RS:"")$0;next}/# SDB_ING_USER/{u=1}u && /^roleOccupant:/{next}u && !NF{print r; u=""}1;END{if(u)print r}' file1 file2

更好的可读性:

awk '
     FNR==NR{
          r=(r!=""?r RS:"")$0;
          next
     }
     /# SDB_ING_USER/{
          u=1
     }
     u && /^roleOccupant:/{
         next
    }
    u && !NF{
         print r; 
         u=""
    }1
    END{
         if(u)print r
    }
    ' file1 file2

<强>解释

  • FNR==NR{r=(r!=""?r RS:"")$0;next}此块我们只读file1并保存变量r中的file1行,由记录分隔符RS分隔,FNR==NR将是如果awk读取第一个文件,则为true。

  • /# SDB_ING_USER/{u=1}如果file2中的行包含/..../中的正则表达式,则设置变量u=1

  • u && /^roleOccupant:/{next}如果设置了变量u,并且行以roleOccupant开头,请跳过此行,然后从file2

  • u && !NF{print r; u=""}如果设置了变量u,则!NF表示空行(NF不会记录记录中的字段,NF=0表示空行,!01,这是真实状态),然后打印变量r,并使变量u

  • 无效 最后的
  • }1 1执行默认操作,即打印当前上下文中的当前记录/行/行,此默认操作仅在上述语句中未跳过记录时才会执行。

<强>文件1:

$ cat file1
roleOccupant: uid1
roleOccupant: uid2
roleOccupant: uid45
roleOccupant: uid80

<强> file2的:

$ cat file2
# SDB_ING_USER
objectClass: organizationalRole
objectClass: top
cn: SDB_ING_USER
description: SDB Ing User Role
roleOccupant: uid1
roleOccupant: uid7
roleOccupant: uid67

# SDB_REGISTERY_USER: 
objectClass: organizationalRole
objectClass: top
cn: SDB_REGISTRY_USER
description: SDB Registry Admin Role
roleOccupant: uid2
roleOccupant: uid34
roleOccupant: uid15

<强>输出:

$ awk 'FNR==NR{r=(r!=""?r RS:"")$0;next}/# SDB_ING_USER/{u=1}u && /^roleOccupant:/{next}u && !NF{print r; u=""}1;END{if(u)print r}' file1 file2
# SDB_ING_USER
objectClass: organizationalRole
objectClass: top
cn: SDB_ING_USER
description: SDB Ing User Role
roleOccupant: uid1
roleOccupant: uid2
roleOccupant: uid45
roleOccupant: uid80

# SDB_REGISTERY_USER: 
objectClass: organizationalRole
objectClass: top
cn: SDB_REGISTRY_USER
description: SDB Registry Admin Role
roleOccupant: uid2
roleOccupant: uid34
roleOccupant: uid15

答案 2 :(得分:0)

如果输入文件是sdb.txt而文件x是x.txt,我使用sed命令文件cmd.sed来执行此操作:

sed -f cmd.sed sdb.txt

sed.cmd

# Within the section from SDB_ING_USER to a blank line
/SDB_ING_USER/,/^$/{
    # Delete roleOccupant lines
    /roleOccupant/d
    # At the blank line
    /^$/{
        # Read x.txt into the output stream
        r x.txt
        # Append a blank line to the output stream
        a
        # Delete the blank line from the input stream
        # (Prevents a blank line before the x.txt content)
        d
    }
}

这是使用sed命令文件而不是单行sed命令完成的,因为sed ra命令需要换行符,因此尝试使用它们很痛苦单行。(参见下面有关换行的编辑和-e

输出:

$ sed -f cmd.sed sdb.txt
# SDB_ING_USER
objectClass: organizationalRole
objectClass: top
cn: SDB_ING_USER
description: SDB Ing User Role
roleOccupant: uid1
roleOccupant: uid2
roleOccupant: uid45
roleOccupant: uid80

# SDB_REGISTERY_USER: 
objectClass: organizationalRole
objectClass: top
cn: SDB_REGISTRY_USER
description: SDB Registry Admin Role
roleOccupant: uid2
roleOccupant: uid34
roleOccupant: uid15

EDIT。看看potong使用e cat允许将x.txt文件读入模式空间(而不是输出流)并意识到在命令行中你可以使用多个-e参数来获得有效行单线sed命令中断。

所以这是一个新的单行:

sed -e '/SDB_ING_USER/,/^$/{' -e '/roleOccupant/d' -e '/^$/e cat x.txt' -e '}' sdb.txt

答案 3 :(得分:0)

这可能适合你(GNU sed):

sed '/SDB_ING_USER/,/^\s*$/!b;/roleOccupant/d;/^\s*$/e cat x' file

关注SDB_ING_USER与下一个空行之间的界限。删除包含字符串roleOccupant的所有行,并在空行前插入文件x