Bash 如何逐行使用sed?

Bash 如何逐行使用sed?,bash,ubuntu,awk,sed,Bash,Ubuntu,Awk,Sed,我知道我做错了什么,但我不知道是什么 #!/bin/bash while IFS='' read -r line do new=$(git log -1 --pretty="format:%ct" $line) sed "s|$line: .*|: $new|" file.yml done < <(awk 'NR>1{sub(/:.*/,"");print $1}' file.yml) 那么,我想做什么 我有file.yml,

我知道我做错了什么,但我不知道是什么

#!/bin/bash

while IFS='' read -r line
    do
        new=$(git log -1 --pretty="format:%ct" $line)
        sed "s|$line: .*|: $new|" file.yml
    done < <(awk 'NR>1{sub(/:.*/,"");print $1}' file.yml)
那么,我想做什么

我有
file.yml
,带有一些文件源和UNIX时间戳(上次修改日期)。我想用
git log
检查每个文件。从
git log
我收到新的时间戳修改日期,我需要用新日期替换旧日期

我所期望的是:

catalog/view/css/animate.css/3.1.1/animate.min.css: 1484135987
catalog/view/fonts/cinzel/fonts.css: 1484136578
我得到了什么(因此我认为
sed
无法逐行工作):

sed
输出文件内容,不修改文件

$line:.*
将匹配整行,因此它将删除该行,并将整行替换为
:$new

如果您有GNU sed,您可以使用
-i
sed参数就地修改文件:

sed -i "s|$line: .*|$line: $new|" file.yml
或者更好:

sed -i "s|\($line: \).*|\1$new|" file.yml
但是你不能同时读写同一个文件

另外,
sub(/:.*/,“”)
看起来很奇怪-只要用
作为分隔符阅读,这就是IFS的用途<代码>当IFS=:read-r行忽略其余部分;做已完成新建_file.yml mv new_file.yml file.yml 如果确实要进行就地编辑,请首先缓存文件,以便不会同时读取和写入同一文件

readarray -t files < <(awk 'NR>1{sub(/:.*/,"");print $1}' file.yml)
for line in "${files[@]}"; do
    new=$(git log -1 --pretty="format:%ct" "$line")
    sed -i "s|\($line: \).*|\1$new|" file.yml
done

readarray-t文件
sed 's/\(^.*\): \(.*\)/echo \1: $(code_to_get_new_timestamp)/e' file.yml

<代码>:$$行:*$:“< /代码>:您正在输出文件内容并替换整个行。好的,有什么建议?建议:1)将示例简化为两个文件(在该大的输出块中有太多的东西);2)考虑建立一个新的时间戳文件,当完成时只覆盖原始文件。(或者将原始文件归档,并将新文件重命名为
file.yml
);至于从
file.yml
中提取文件名,
awk-F:“{print$1}”
cut-d:”-f1
更易于阅读/理解,谢谢。主要问题是,像在循环中一样更改每个文件中的时间戳。
sed -i "s|\($line: \).*|\1$new|" file.yml
{
   IFS= read -r preserve_first_line
   printf "%s\n" "$preserve_first_line"
   while IFS=':' read -r line _; do
       new=$(git log -1 --pretty="format:%ct" "$line")
       echo "$line: $new"
   done
} < file.yml > new_file.yml
mv new_file.yml file.yml
readarray -t files < <(awk 'NR>1{sub(/:.*/,"");print $1}' file.yml)
for line in "${files[@]}"; do
    new=$(git log -1 --pretty="format:%ct" "$line")
    sed -i "s|\($line: \).*|\1$new|" file.yml
done
sed 's/\(^.*\): \(.*\)/echo \1: $(code_to_get_new_timestamp)/e' file.yml