删除文件的多个模式
Remove multiple patterns of a file
我有以下文件,我们称它为user.txt:
2020/06/30 22:02:58 > [+] VALID USERNAME: admin@spookysec.local
2020/06/30 22:03:58 > [+] VALID USERNAME: admin-svc@spookysec.local
2020/06/30 22:04:58 > [+] VALID USERNAME: backup@spookysec.local
2020/06/30 22:05:58 > [+] VALID USERNAME: harry@spookysec.local
2020/06/30 22:06:58 > [+] VALID USERNAME: wrgwrsd@spookysec.local
2020/06/30 22:07:58 > [+] VALID USERNAME: brssdb@spookysec.local
2020/06/30 22:09:58 > [+] VALID USERNAME: a@spookysec.local
2020/06/30 22:10:58 > [+] VALID USERNAME: adm@spookysec.local
2020/06/30 22:11:58 > [+] VALID USERNAME: admifdfdsn@spookysec.local
我想删除每一行的多个模式,以获取每行一个用户名的用户名(例如 admin、admin-sv)。
我尝试了两个单独的 sed,效果很好,
sed -r 's/.{16}$//' user.txt > user2.txt
之后
sed -r 's/.{42}//' user2.txt > user3.txt
但我认为有一种更快、更性感的方法可以做到这一点。
尤其是这个命令
sed -r 's/(@\D+)$//' user.txt > user2.txt
不起作用。我想把@和后面的每一个字符都删掉...
有没有人知道我做错了什么以及可能的解决方案?如果我能用sed或grep达到我的目标就更好了。
你可以试试这个sed
:
sed -E 's/.*[[:blank:]]|@.*//g' file
admin
admin-svc
backup
harry
wrgwrsd
brssdb
a
adm
admifdfdsn
解释:
.*[[:blank:]]
:匹配任何0个或多个字符后跟一个空格的字符串
|
: 或
@.*
:匹配 @
以及之后的所有内容
使用您展示的示例,请尝试以下代码。
第一个解决方案: 使用awk
,这可以用更简单的方式完成,尝试一次。
awk -F'VALID USERNAME:[[:space:]]+|@' '{print }' Input_file
说明:这里使用awk
编程。将 VALID USERNAME:[[:space:]]+|@
作为整个 Input_file 的字段分隔符并根据要求打印每行的第二个字段。
第二个解决方案: 使用 GNU grep
请尝试以下。
grep -oP 'VALID USERNAME:[[:space:]]+\K[^@]*' Input_file
说明: 使用 GNU grep
的 -oP
选项,其中 -o 仅打印匹配值和 -P
启用 PCRE 正则表达式。在 grep
的主程序中匹配 VALID USERNAME:[[:space:]]+
正则表达式,然后是 \K
(这将忘记以前匹配的值,以便不打印它们),然后匹配 @ 之前的所有内容以获取实际用户根据 OP 显示的样本命名。
另一个使用 sed 和捕获组的变体,在替换中使用组 1 </code>:</p>
<pre><code>sed -E 's/.*[[:blank:]]([^@[:blank:]]+)@.*//' file
.*[[:blank:]]
匹配到最后space
([^@[:blank:]]+)
在组 1 中捕获匹配 @
或 spaces 以外的 1+ 个字符
@.*
匹配 @
和行的其余部分
输出
admin
admin-svc
backup
harry
wrgwrsd
brssdb
a
adm
admifdfdsn
另一个使用 awk 的选项,您可以在 @
上拆分最后一列
如果split返回了2部分,可以打印第一部分:
awk '{
nr=split($(NF), a, "@")
if (nr==2) print a[1]
}' file
我会使用:
sed 's/.*[[:space:]]\([^[:space:]]\)//; s/@.*//'
这个和 anubhava 的(好的)答案之间的细微差别在于,如果一行末尾有杂散的白色 space,它仍然有效。
可能 unnecessary/paranoid,但视情况而定,我喜欢允许这样的情况。
如果列不同,您可以使用:
sed -E 's/(.*VALID[[:space:]]+USERNAME:[[:space:]]+)([^@[:space:]]+)(.*)//'
这匹配行中任意位置的 VALID USERNAME:
,并打印下一个字段,直到但不包括第一个 @
或 whitespace 字符。您也可以根据您的数据将模式更改为 USERNAME:
或类似模式。
最后,如果未找到 @
(即电子邮件字段为空或无效),这些变体会跳过一行:
sed -n 's/.*[[:blank:]]\([^[:space:]]\)//; s/@.*//p'
sed -En 's/(.*VALID[[:space:]]+USERNAME:[[:space:]]+)([^@]+)(@.*)//p'
这可能适合您 (GNU sed):
sed -nE 's/.*\<([^@]*)@.*//p' file
捕获并打印最后一个 @
字符之前的单词。
我有以下文件,我们称它为user.txt:
2020/06/30 22:02:58 > [+] VALID USERNAME: admin@spookysec.local
2020/06/30 22:03:58 > [+] VALID USERNAME: admin-svc@spookysec.local
2020/06/30 22:04:58 > [+] VALID USERNAME: backup@spookysec.local
2020/06/30 22:05:58 > [+] VALID USERNAME: harry@spookysec.local
2020/06/30 22:06:58 > [+] VALID USERNAME: wrgwrsd@spookysec.local
2020/06/30 22:07:58 > [+] VALID USERNAME: brssdb@spookysec.local
2020/06/30 22:09:58 > [+] VALID USERNAME: a@spookysec.local
2020/06/30 22:10:58 > [+] VALID USERNAME: adm@spookysec.local
2020/06/30 22:11:58 > [+] VALID USERNAME: admifdfdsn@spookysec.local
我想删除每一行的多个模式,以获取每行一个用户名的用户名(例如 admin、admin-sv)。 我尝试了两个单独的 sed,效果很好,
sed -r 's/.{16}$//' user.txt > user2.txt
之后
sed -r 's/.{42}//' user2.txt > user3.txt
但我认为有一种更快、更性感的方法可以做到这一点。
尤其是这个命令
sed -r 's/(@\D+)$//' user.txt > user2.txt
不起作用。我想把@和后面的每一个字符都删掉...
有没有人知道我做错了什么以及可能的解决方案?如果我能用sed或grep达到我的目标就更好了。
你可以试试这个sed
:
sed -E 's/.*[[:blank:]]|@.*//g' file
admin
admin-svc
backup
harry
wrgwrsd
brssdb
a
adm
admifdfdsn
解释:
.*[[:blank:]]
:匹配任何0个或多个字符后跟一个空格的字符串|
: 或@.*
:匹配@
以及之后的所有内容
使用您展示的示例,请尝试以下代码。
第一个解决方案: 使用awk
,这可以用更简单的方式完成,尝试一次。
awk -F'VALID USERNAME:[[:space:]]+|@' '{print }' Input_file
说明:这里使用awk
编程。将 VALID USERNAME:[[:space:]]+|@
作为整个 Input_file 的字段分隔符并根据要求打印每行的第二个字段。
第二个解决方案: 使用 GNU grep
请尝试以下。
grep -oP 'VALID USERNAME:[[:space:]]+\K[^@]*' Input_file
说明: 使用 GNU grep
的 -oP
选项,其中 -o 仅打印匹配值和 -P
启用 PCRE 正则表达式。在 grep
的主程序中匹配 VALID USERNAME:[[:space:]]+
正则表达式,然后是 \K
(这将忘记以前匹配的值,以便不打印它们),然后匹配 @ 之前的所有内容以获取实际用户根据 OP 显示的样本命名。
另一个使用 sed 和捕获组的变体,在替换中使用组 1 </code>:</p>
<pre><code>sed -E 's/.*[[:blank:]]([^@[:blank:]]+)@.*//' file
.*[[:blank:]]
匹配到最后space([^@[:blank:]]+)
在组 1 中捕获匹配@
或 spaces 以外的 1+ 个字符
@.*
匹配@
和行的其余部分
输出
admin
admin-svc
backup
harry
wrgwrsd
brssdb
a
adm
admifdfdsn
另一个使用 awk 的选项,您可以在 @
如果split返回了2部分,可以打印第一部分:
awk '{
nr=split($(NF), a, "@")
if (nr==2) print a[1]
}' file
我会使用:
sed 's/.*[[:space:]]\([^[:space:]]\)//; s/@.*//'
这个和 anubhava 的(好的)答案之间的细微差别在于,如果一行末尾有杂散的白色 space,它仍然有效。
可能 unnecessary/paranoid,但视情况而定,我喜欢允许这样的情况。
如果列不同,您可以使用:
sed -E 's/(.*VALID[[:space:]]+USERNAME:[[:space:]]+)([^@[:space:]]+)(.*)//'
这匹配行中任意位置的 VALID USERNAME:
,并打印下一个字段,直到但不包括第一个 @
或 whitespace 字符。您也可以根据您的数据将模式更改为 USERNAME:
或类似模式。
最后,如果未找到 @
(即电子邮件字段为空或无效),这些变体会跳过一行:
sed -n 's/.*[[:blank:]]\([^[:space:]]\)//; s/@.*//p'
sed -En 's/(.*VALID[[:space:]]+USERNAME:[[:space:]]+)([^@]+)(@.*)//p'
这可能适合您 (GNU sed):
sed -nE 's/.*\<([^@]*)@.*//p' file
捕获并打印最后一个 @
字符之前的单词。