我需要更改文件的 md5,有时一次,有时多次。一个朋友给了我这个脚本来在文件末尾添加一个字符串,但我想我可能会多次添加它,当我在十六进制编辑器中查看时,我看到了它两次。我也不确定这是否真的在编辑其他内容。只是想在开始使用之前检查一下。
#!/bin/sh
echo "md5change`date +%s`"
cat $1 | sed --in-place '/md5change/s/.*//' $1
sed -i '/^[ \t]*$/d' $1
echo "md5change`date +%s`" >> $1
echo "done"
谢谢
答案1
该脚本似乎假定文件中有一行(或多行)包含字符串“md5change”。它在屏幕上显示这样的字符串,清空(但不删除)包含该字符串的行,然后删除文件中的所有空行,最后将新的“md5change”行附加到文件中(这不一定与第一个显示一个echo
),最后打印“完成”。不过,您必须删除该cat $1 |
部分,因为$1
它已经作为 的“就地”参数呈现sed
。
编辑:我想你可以压缩你的代码,例如:
timestamp=md5change$(date +%s)
echo "${timestamp}"
sed -i "/md5change/s/.*/${timestamp}/" "$1"
echo "done"
(注意:此代码不等于您的代码模板,因为您的代码删除文件中的所有空行,删除文件中的多个“md5change”条目,并附加到文件末尾。此紧凑版本更改现有的“ md5change”条目由新的条目组成。我的猜测是,这就是您真正想要的,并且它修复了原始代码的一些问题。)
答案2
你快到了!这是使用您选择的工具的单行解决方案,sed
并且date
:
$ sed -i "s/^md5change.*/md5change$(date +%s)/" FILE
我不知道为什么你想要第二个sed
命令(它删除所有缺少非空格字符的行,尽管非 GNUsed
可能无法识别\t
)。假设是 GNU,请添加; /^[ \t]$/d
到引用部分的末尾。如果没有 GNU,只需用文字制表符代替转义版本即可。
如果您还没有“md5change”行,单行代码将无法工作。为此,您首先需要另一行:
#!/bin/sh
epoch=$(date +%s)
if grep ^md5change "$1"
then sed -i "s/^md5change.*/md5change$epoch/" "$1"
else echo "md5change$epoch" >> "$1"
fi
请注意,这date +%s
是不是便携的! POSIX 标准没有指定它,尽管 GNU 和 BSD 版本都date
支持它。您可以使用perl -e "print time"
或以真实语言执行所有逻辑(例如perl
):
#!/usr/bin/perl -i -pn
$_ = $1 . time . "\n" if /^(md5change)/
$1
这会查找以“md5change”开头的行,然后将其替换为与纪元连接的 匹配部分( “md5change”),然后是换行符。-i
将覆盖输入(就像sed -i
– 与 相同sed --in-place
),使用表示当前行-n
的默认变量 ( ) 迭代输入的每一行,并在命令末尾打印(每行)。$_
-p
$_
-e
要删除空行,请将 perl 的-pn
参数转换为-n
并在末尾添加一个新行,其中显示print if /\S/
您也可以将该脚本转换为命令行的单行脚本:
$ perl -i -pne '$_ = $1 . time . "\n" if /^(md5change)/'
或者
$ perl -i -ne '$_ = $1 . time . "\n" if /^(md5change)/; print if /\S/'
要处理缺少“md5change”行的输入文件:
#!/usr/bin/perl -i
my $md5change = 0;
while (<>) {
if (/^(md5change)/) {
$_ = $1 . time . "\n";
$md5change = 1;
}
print;
} continue {
if (eof and not $md5change) {
$md5change = 0;
print "md5change" . time . "\n";
}
}