【问题标题】:Change a string using sed or awk使用 sed 或 awk 更改字符串
【发布时间】:2019-09-16 22:00:22
【问题描述】:

我有一些文件的时间和日期有误,但文件名包含正确的时间和日期,我尝试编写一个脚本来使用 touch 命令修复此问题。

文件名示例: 071212_090537.jpg

我希望将其转换为以下格式: 1712120905.37

注意,年份在文件名中列为07,即使是17,所以我希望将第一个0改为1。

如何使用 awk 或 sed 做到这一点?

我对 awk 和 sed(一般来说是一种编程)很陌生。已尝试搜索解决方案和说明,但无法弄清楚如何解决此问题。

谁能帮帮我?

谢谢。 :)

【问题讨论】:

  • 欢迎来到 SO。 Stack Overflow 是一个专为专业和热情的程序员准备的问答页面。将您自己的代码添加到您的问题中。您应该至少展示自己为解决这个问题所做的研究。

标签: awk sed


【解决方案1】:

举个例子:

awk -F'[_.]' '{$0=$1$2;sub(/^./,"1");sub(/..$/,".&")}1'<<<"071212_090537.jpg"

将输出:

1712120905.37

如果要删除文件,可以让 awk 生成mv origin new 命令,并将输出通过管道传输到|sh,例如:(cmets inline)

listYourFiles|    # list your files as input to awk

       awk -F'[_.]' '{o=$0;$0=$1$2;sub(/^./,"1");sub(/..$/,".&");
                      printf "mv %s %s\n",o,$0 }1' #this will print "mv ori new"

             |sh     # this will execute the mv command

【讨论】:

  • 非常感谢。这帮助我走上了正确的轨道。我最终为我的 shell 脚本使用了以下代码: datetime=$(basename "$filename" .jpg | awk -F'[_]' '{$0=$1$2;sub(/^./,"1") ;sub(/..$/,".&"); print}')
  • @Kent,看,这就是为什么我们不只是向菜鸟扔神秘的单线。现在他正在为每个文件生成两个管道和一个proc。
  • mv 正在生成不带引号的文本,因此您想要的文件名对 shell 开放以进行解释/通配符/通配符扩展。应该是printf "mv -- \047%s\047 \047%s\047\n",o.$0/
  • 我会将这个 sub(/^./,"1") 更改为 sub(/^0/,"1") 只是为了避免正则表达式中 . 的危险
【解决方案2】:

完全没有必要为此调用 awk 或 sed,您可以在 shell 中进行。例如用 bash:

$ f='071212_090537.jpg'
$ [[ $f =~ ^.(.*)_(.*)(..)\.[^.]+$ ]]
$ echo "1${BASH_REMATCH[1]}${BASH_REMATCH[2]}.${BASH_REMATCH[3]}"
1712120905.37

这可能是你想要做的:

for old in *.jpg; do
    [[ $old =~ ^.(.*)_(.*)(..)\.[^.]+$ ]] || { printf 'Warning, unexpected old file name format "%s"\n' "$old" >&2; continue; }
    new="1${BASH_REMATCH[1]}${BASH_REMATCH[2]}.${BASH_REMATCH[3]}"
    [[ -f "$new" ]] && { printf 'Warning, new file name "%s" generated from "%s" already exists, skipping.\n' "$new" "$old" >&2; continue; }
    mv -- "$old" "$new"
done

您需要对已经存在的新测试进行测试,因为旧的 071212_090537.jpg171212_090537.jpg(或各种其他值)会创建相同的新 1712120905.37

【讨论】:

    【解决方案3】:

    我认为 sed 确实是最简单的解决方案:

    你可以这样做:

    ▶ for f in *.jpg ; do
      new_f=$(sed -E 's/([0-9]{6})_([0-9]{4})([0-9]{2})\.jpg/\1\2.\3.jpg/' <<< $f)
      mv $f $new_f
    done
    

    更多信息:

    • 您可能需要阅读有关正则表达式的介绍性教程。

    • 请注意,sed 的 -E 选项允许使用扩展的正则表达式,从而在此处提供更易读和方便的表达式。

    • &lt;&lt;&lt; 的使用是一种被称为“此处字符串”的 Bashism。如果你使用的 shell 不支持,A &lt;&lt;&lt; $b 可以重写为echo $b | A

    测试:

    ▶ touch 071212_090538.jpg 071212_090539.jpg                                                                                                                                                           
    ▶ ls -1 *.jpg
    071212_090538.jpg
    071212_090539.jpg
    ▶ for f in *.jpg ; do
      new_f=$(sed -E 's/([0-9]{6})_([0-9]{4})([0-9]{2})\.jpg/\1\2.\3.jpg/' <<< $f)
      mv $f $new_f
    done
    ▶ ls -1
    0712120905.38.jpg
    0712120905.39.jpg
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-08
      • 1970-01-01
      • 1970-01-01
      • 2021-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多