例如,这是 md5sum 命令的输出:
35c9581c469c366e286be708a9d9f939 input.txt
这是我正在运行的命令行:
md5sum input.txt | sed -f script.sed
我想让 md5sum 的输出如下所示:
35c9xxxxxxxxxxxxxxxxxxxxxxxxxxxx input.txt
目前,我的 .sed 脚本包含以下内容,它会编辑除前 4 个字符之外的所有内容:
s/./x/5g
当它看到空格“”时,我需要让它停止这样做。有什么想法吗?
答案1
如果 (md5sum) 散列;那么这就可以完成工作(在支持大括号扩展的外壳中)
sed -e's/./x/'{5..32} infile
else 对于任何字符长度,直到看到第一个字符空间;然后:
使用sed
, 和 作为通用解决方案:
sed -E ':a s/^(.{4}x{0,})[^x ]/\1x/;ta' infile
:a
是一个sed我们命名的标签a
s/
替换下面的匹配项^
是行锚点的开始(
开启小组赛.
匹配单个字符.{4}
匹配 4 个字符(或仅....
),后跟x{0,}
0 个或多个x
字符 (或x*
)
)
小组比赛结束和后向参考是\1
[^x ]
匹配除 strings 之外的任何字符x
,(在字符类中,如果它是紧接着在 中
^
打开后的第一个字符,则否定匹配);[
[^...]
/
与下面\1
是对上面匹配的部分进行反向引用(...)
,因此我们将第一个部分再次返回到其位置,但后来x
添加了额外的内容。- 然后一个
x
;还记得上面我们没有[^x ]
在小组赛中取得进球吗(...)
?这些是我们x
现在要一一替换的字符。
/
替换结束;
开始一个新命令ta
a
如果替换成功则跳转到标签;如果不是,则意味着我们将所有字符替换为x
,现在没有剩余字符来替换并结束sed
命令。
答案2
md5sum
始终为哈希生成 32 个字符的输出。您可以先查找 32 个字符,然后查找空格,然后用 X 替换最后 28 个字符,而不是检测空格。
md5sum input.txt | sed -E 's/^([[:xdigit:]]{4})[[:xdigit:]]{28} /\1xxxxxxxxxxxxxxxxxxxxxxxxxxxx /'
35c9xxxxxxxxxxxxxxxxxxxxxxxxxxxx input.txt
分解声明:
's/^([[:xdigit:]]{4})[[:xdigit:]]{28} /\1xxxxxxxxxxxxxxxxxxxxxxxxxxxx /'
's/A / B /'
we're substituting patterns matching A with B
's/ [[:xdigit:]] [[:xdigit:]] / /'
we're looking for two groups of hexadecimal characters
's/ [[:xdigit:]]{4} [[:xdigit:]]{28} / /'
The first group has exactly four characters
The second group has exactly twenty-eight characters
's/ ([[:xdigit:]]{4})[[:xdigit:]]{28} / /'
The first group is a "capture group" which we can reference later
's/ ([[:xdigit:]]{4})[[:xdigit:]]{28} /\1 /'
We will print out the first group verbatim in the output
's/ ([[:xdigit:]]{4})[[:xdigit:]]{28} /\1xxxxxxxxxxxxxxxxxxxxxxxxxxxx /'
We will print x's followed by a space for the next 28 characters
's/^([[:xdigit:]]{4})[[:xdigit:]]{28} /\1xxxxxxxxxxxxxxxxxxxxxxxxxxxx /'
The statement must appear at the start of a line and have a space at the end.
答案3
Perl 方法:
$ md5sum file | perl -ple 's/^(.{4})(\S+)(\s+.*)/$1 . "x" x length($2) . $3/e'
9191xxxxxxxxxxxxxxxxxxxxxxxxxxxx file
这将找到前 4 个字符 ( ^(.{4})
),然后是尽可能多的非空白字符 ( (\S+)
),然后是第一个或多个空格,后跟任何内容,直到行尾 ( (\s+.*)
)。然后将其替换为第一个捕获的值($1
,前 4 个字符),该字符串x
重复的次数与第二个捕获组的长度 ( "x" x length($2)
) 相同,然后是最终捕获的组$3
。需要替换运算符末尾的/e
来允许我们计算s///
.
当然,如果您知道您将始终运行md5sum
,因此散列的长度 - 4 将始终为 28,您可以简化为:
$ md5sum file | perl -ple 's/^(.{4})(\S+)/$1 . "x" x 28/e'
9191xxxxxxxxxxxxxxxxxxxxxxxxxxxx file
甚至:
$ md5sum file | perl -ple 's/(?<=.{4})(\S+)/"x" x 28/e'
9191xxxxxxxxxxxxxxxxxxxxxxxxxxxx file
答案4
$ md5sum somefile
d68610fdffd770de94818268899d6abb somefile
$ md5sum somefile | { read -r hash pathname; printf '%.4sxxxxxxxxxxxxxxxxxxxxxxxxxxxx %s\n' "$hash" "$pathname" }
d686xxxxxxxxxxxxxxxxxxxxxxxxxxxx somefile
这会将哈希值和路径名读取到两个 shell 变量中,然后将它们打印出来,并将哈希值的最后 28 个字符替换为x
。
要支持多个文件,请使用循环:
$ md5sum somefile* | while read -r hash pathname; do printf '%.4sxxxxxxxxxxxxxxxxxxxxxxxxxxxx %s\n' "$hash" "$pathname"; done
d41dxxxxxxxxxxxxxxxxxxxxxxxxxxxx somefile
d686xxxxxxxxxxxxxxxxxxxxxxxxxxxx somefile1
d41dxxxxxxxxxxxxxxxxxxxxxxxxxxxx somefile2