替换所有字符,直到看到特定字符

替换所有字符,直到看到特定字符

例如,这是 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现在要一一替换的字符。
  • /替换结束
  • ;开始一个新命令
  • taa如果替换成功则跳转到标签;如果不是,则意味着我们将所有字符替换为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

相关内容