[英]How can I replace lines in a text file with lines from another file based on matching pattern?
I want to replace some lines in a file with lines from another file based on matching a pattern. 我想基于匹配模式用另一个文件中的行替换文件中的某些行。 I want to replace every line that begin with "rolOccupant" after finding "# SBD_ING_USER" to the empty line with content from file x 我想用“#SBD_ING_USER”替换每行以“rolOccupant”开头的行,其中包含来自文件x的内容的空行
File x 档案x
roleOccupant: uid1
roleOccupant: uid2
roleOccupant: uid45
roleOccupant: uid80
Input file 输入文件
# 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 file 输出文件
# 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
awk one-liner awk one-liner
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=
to set empty line as the Record Separator -v RS=
将空行设置为记录分隔符
FNR==NR{a=a$0; next}
FNR==NR{a=a$0; next}
: This will store your File X
contents in variable a
FNR==NR{a=a$0; next}
:这将把你的File X
内容存储在变量a
/# SDB_ING_USER/ {gsub(/roleOccupant.*/,a ORS)}
: While iterating over your Input file
if record contains # SDB_ING_USER
then substitute all lines starting from roleOccupant
to end of record with a ORS
in other words a "\\n"
/# SDB_ING_USER/ {gsub(/roleOccupant.*/,a ORS)}
:在记录包含# SDB_ING_USER
迭代Input file
,然后将从roleOccupant
开始的所有行roleOccupant
为带有a ORS
的记录结尾,换句话说a "\\n"
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
Using awk
使用awk
One-liner: 一内胆:
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
Better Readable: 更好的可读性:
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
Explanation: 说明:
FNR==NR{r=(r!=""?r RS:"")$0;next}
This block we read only file1
and save file1 rows in variable r
, separated by record separator RS
, FNR==NR
will be true, only when awk
reads first file. FNR==NR{r=(r!=""?r RS:"")$0;next}
这个块我们只读取file1
并保存变量r
file1行,用记录分隔符RS
分隔, FNR==NR
将是是的,仅当awk
读取第一个文件时。
/# SDB_ING_USER/{u=1}
if line from file2
, contains regexp in /..../
then, set variable u=1
/# SDB_ING_USER/{u=1}
如果来自file2
行,在/..../
包含regexp,则设置变量u=1
u && /^roleOccupant:/{next}
if variable u
is set, and line starts with roleOccupant
, skip such line, and go to next record, from file2
u && /^roleOccupant:/{next}
如果设置了变量u
,并且行以roleOccupant
,则跳过这样的行,然后从file2
转到下一条记录
u && !NF{print r; u=""}
u && !NF{print r; u=""}
if variable u
is set, and !NF
, meaning empty line ( NF
gives no of fields in record, NF=0
means blank line, !0
is 1
, which is true state), then print variable r
, and nullify variable u
u && !NF{print r; u=""}
如果变量u
被设置,并且!NF
,意味着空行( NF
给出记录中的字段, NF=0
表示空行, !0
是1
,这是真状态),然后打印变量r
,并使变量u
无效
}1
1 at the end does default operation, thats print current record/row/line, in current context, this default operation takes only if record not skipped in above, statements. 最后的}1
1执行默认操作,即打印当前上下文中的当前记录/行/行,此默认操作仅在上面的语句中未跳过记录时才采用。
file1: 文件1:
$ cat file1
roleOccupant: uid1
roleOccupant: uid2
roleOccupant: uid45
roleOccupant: uid80
file2: 文件2:
$ 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
Output: 输出:
$ 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
Where the input file is sdb.txt
and file x is x.txt
, I use a sed command file cmd.sed
to do this: 如果输入文件是sdb.txt
而文件x是x.txt
,我使用sed命令文件cmd.sed
来执行此操作:
sed -f cmd.sed sdb.txt
sed.cmd
: 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 } }
This is done with a sed command file rather than as a single line sed command bcause the sed r
and a
commands require a newline, so they are painful to try to use in a one-liner. 这是用sed命令文件,而不是作为bcause sed的单行sed命令完成r
和a
命令需要一个换行符, 所以他们是痛苦的尝试在一个班轮使用。 (See EDIT below regarding newlines and -e
) (有关换行符和-e
请参阅下面的编辑)
Output: 输出:
$ 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. 编辑。 Looked at potong's use of e cat
which allows reading the x.txt file into the pattern space (rather than output stream) AND realized that at the command line you can just use multiple -e
arguments to get effective line breaks in one-liner sed commands. 看看potong对e cat
的使用,它允许将x.txt文件读入模式空间(而不是输出流)并意识到在命令行中你可以使用多个-e
参数来获得单行sed中的有效换行符命令。
So here's a new one-liner: 所以这是一个新的单行:
sed -e '/SDB_ING_USER/,/^$/{' -e '/roleOccupant/d' -e '/^$/e cat x.txt' -e '}' sdb.txt
This might work for you (GNU sed): 这可能适合你(GNU sed):
sed '/SDB_ING_USER/,/^\s*$/!b;/roleOccupant/d;/^\s*$/e cat x' file
Focus on the lines between SDB_ING_USER
and the next empty line. 专注于SDB_ING_USER
和下一个空行之间的SDB_ING_USER
。 Delete any lines containing the string roleOccupant
and insert file x
before the empty line. 删除包含字符串roleOccupant
所有行,并在空行之前插入文件x
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.