sed命令删除第一次出现的单词
sed command to remove first occurrence of a word
我想知道如何删除文件中第一次出现的单词。
示例:我想删除第一次出现的管理员。
account required pam_opendirectory.so
account sufficient pam_self.so
account required pam_group.so no_warn group=admin,wheel fail_safe
account required pam_group.so no_warn deny group=admin,wheel ruser fail_safe
我试过:
sudo sed -i.bak "s/admin,//1" /etc/pam.d/screensaver
但这两种情况都删除了,有什么想法吗?
使用 sed
要删除文件中的第一个匹配项:
$ sed -e ':a' -e '$!{N;ba;}' -e 's/admin,//1' file
account required pam_opendirectory.so
account sufficient pam_self.so
account required pam_group.so no_warn group=wheel fail_safe
account required pam_group.so no_warn deny group=admin,wheel ruser fail_safe
(以上是用 GNU sed 测试的。)
工作原理
-e ':a' -e '$!{N;ba;}'
这会立即将整个文件读入模式 space。 (如果您的文件对内存来说太大,这不是一个好方法。)
-e 's/admin,//1'
这会在 admin
第一次出现且仅在第一次出现时执行替换。
使用 BSD (OSX) sed
Wintermute 报告 BSD sed 不能在单行中执行分支指令,并建议使用此替代方法来更改文件:
sed -i.bak -n '1h; 1!H; $ { x; s/admin,//; p; }' file
这会立即读取整个文件,然后在读取最后一行后进行替换。
更详细:
-n
默认情况下,sed 会打印每一行。这将关闭它。
1h
这会将第一行放入保留缓冲区。
1!H
对于所有后续行,这将它们追加到保留缓冲区。
$ { x; s/admin,//; p; }
对于最后一行 ($),这将交换保持和模式缓冲区,以便模式缓冲区现在具有完整的文件。 s/admin,//
进行替换,p
打印结果。
使用 awk
$ awk '/admin/ && !f{sub(/admin,/, ""); f=1} 1' file >file.tmp && mv file.tmp file
这导致:
account required pam_opendirectory.so
account sufficient pam_self.so
account required pam_group.so no_warn group=wheel fail_safe
account required pam_group.so no_warn deny group=admin,wheel ruser fail_safe
工作原理
/admin,/ && !f{sub(/admin,/, ""); f=1}
对于每一行,检查它是否包含单词 admin,
以及标志 f
是否仍然具有默认值零。如果是这样,请删除第一次出现的 admin,
并将标志设置为一个。
1
打印每一行。 1
是 awk 的神秘 shorthand for {print [=29=]}
.
使用 sed,不读取整个文件:
sed 's/admin,//;tl;b;:l;n;bl' file
这会等待成功替换,然后进入打印文件其余部分的循环。
s/admin,//;tl;b;
:用空字符串替换admin,如果替换发生则跳转到标签l
否则打印该行并退出(下一行将以同样的方式处理)。
:l;n;bl
:定义标签l,读取行,跳转到l。
我想知道如何删除文件中第一次出现的单词。
示例:我想删除第一次出现的管理员。
account required pam_opendirectory.so
account sufficient pam_self.so
account required pam_group.so no_warn group=admin,wheel fail_safe
account required pam_group.so no_warn deny group=admin,wheel ruser fail_safe
我试过:
sudo sed -i.bak "s/admin,//1" /etc/pam.d/screensaver
但这两种情况都删除了,有什么想法吗?
使用 sed
要删除文件中的第一个匹配项:
$ sed -e ':a' -e '$!{N;ba;}' -e 's/admin,//1' file
account required pam_opendirectory.so
account sufficient pam_self.so
account required pam_group.so no_warn group=wheel fail_safe
account required pam_group.so no_warn deny group=admin,wheel ruser fail_safe
(以上是用 GNU sed 测试的。)
工作原理
-e ':a' -e '$!{N;ba;}'
这会立即将整个文件读入模式 space。 (如果您的文件对内存来说太大,这不是一个好方法。)
-e 's/admin,//1'
这会在
admin
第一次出现且仅在第一次出现时执行替换。
使用 BSD (OSX) sed
Wintermute 报告 BSD sed 不能在单行中执行分支指令,并建议使用此替代方法来更改文件:
sed -i.bak -n '1h; 1!H; $ { x; s/admin,//; p; }' file
这会立即读取整个文件,然后在读取最后一行后进行替换。
更详细:
-n
默认情况下,sed 会打印每一行。这将关闭它。
1h
这会将第一行放入保留缓冲区。
1!H
对于所有后续行,这将它们追加到保留缓冲区。
$ { x; s/admin,//; p; }
对于最后一行 ($),这将交换保持和模式缓冲区,以便模式缓冲区现在具有完整的文件。
s/admin,//
进行替换,p
打印结果。
使用 awk
$ awk '/admin/ && !f{sub(/admin,/, ""); f=1} 1' file >file.tmp && mv file.tmp file
这导致:
account required pam_opendirectory.so
account sufficient pam_self.so
account required pam_group.so no_warn group=wheel fail_safe
account required pam_group.so no_warn deny group=admin,wheel ruser fail_safe
工作原理
/admin,/ && !f{sub(/admin,/, ""); f=1}
对于每一行,检查它是否包含单词
admin,
以及标志f
是否仍然具有默认值零。如果是这样,请删除第一次出现的admin,
并将标志设置为一个。1
打印每一行。
1
是 awk 的神秘 shorthand for{print [=29=]}
.
使用 sed,不读取整个文件:
sed 's/admin,//;tl;b;:l;n;bl' file
这会等待成功替换,然后进入打印文件其余部分的循环。
s/admin,//;tl;b;
:用空字符串替换admin,如果替换发生则跳转到标签l
否则打印该行并退出(下一行将以同样的方式处理)。:l;n;bl
:定义标签l,读取行,跳转到l。