使用 Awk 或 Sed 在特定行的末尾添加语句 [英] Using Awk or Sed to tack on a statement at the end of a specific line

查看:27
本文介绍了使用 Awk 或 Sed 在特定行的末尾添加语句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为 poscar1.cif 的文件,我想在该文件的特定行插入一个变量的内容.

I have a file I named poscar1.cif, and I would like to insert the contents of a variable at a specific line in this file.

例如,行 24,当前读取:

For example, line 24, which currently reads:

_cell_length_a

我想添加我的变量 a(在我的函数中定义为 a=5.3827)的内容,这样该行现在显示为:

I would like to tack the contents of my variable a (defined in my function as a=5.3827) so that way the line now reads:

_cell_length_a 5.3827

有没有办法使用 sed 或 awk 来做到这一点?我正在使用 bash 脚本来完成此操作(不幸的是,完整的脚本太大而无法发布).

Is there a way to do this using sed or awk? I am using a bash script to accomplish this (the full script is too large to post, unfortunately).

推荐答案

自资深ed 实用程序不再受到足够的关注:

Since the veteran ed utility doesn't get enough attention anymore:

a=5.3827

ed -s poscar1.cif <<EOF 
g/^_cell_length_a$/ s//& $a/
w
EOF

ed 真正就地编辑文件,不像 sed 带有 -i 选项[1].

ed truly edits a file in place, unlike sed with its -i option[1].

sed 借用了 ed 的许多特性,因此在功能上有很大的重叠,但也有重要的差异,其中一些在这里浮出水面.

sed borrowed many features from ed, so there is significant overlap in functionality, but there are also important differences, some of which surface here.

  • -s 抑制 ed 的状态消息.
  • poscar1.cif 是要就地编辑的输入文件.
  • <<EOF ...here-document 包含 ed 的命令 - ed 要求其命令来自 stdin 并且每个命令都在自己的行上.
  • g/^_cell_length_a$/ ... 是一个(基本的)正则表达式(正则表达式),它匹配所有完全包含 _cell_length_a 的行 - g 确保在根本没有匹配的情况下不会报告错误.
    • 请注意,$ 转义的,以保护它不被 here-document 内的 shell 解释(在这个实例,但是很好的做法).
    • -s suppresses ed's status messages.
    • poscar1.cif is the input file to edit in place.
    • <<EOF ... is the here-document that contains the commands for ed - ed requires its commands to come from stdin and each command to be on its own line.
    • g/^_cell_length_a$/ ... is a (basic) regex (regular expression) that matches all lines that exactly contain _cell_length_a - the g ensures that no error is reported if there's no match at all.
      • Note that the $ is -escaped to protect it from interpretation by the shell inside the here-document (not strictly necessary in this instance, but good practice).
      • 请注意,由于此处文档的开始分隔符 (EOF) 未加引号shell 会发生变量扩展;本质上,shell 将内容视为双引号字符串的内容.
      • Note that since the opening delimiter (EOF) of the here-document is unquoted, shell variable expansions DO take place; in essence, the contents are treated by the shell like the contents of a double-quoted string.
      • 为了调试,使用,p代替w,以便只打印修改后的缓冲区,而不将其写回文件.
      • For debugging, use ,p in place of w so as to only print the modified buffer, without writing it back to the file.

      [1] 重新就地更新:

      更准确地说,ed 保留文件现有的inode,从而确保保留所有文件的属性.
      但是,它不会覆盖现有文件的单个字节,而是整个文件读入内存中的缓冲区,然后写入整个缓冲区要求时转到文件.
      这使得 ed 仅适用于小到足以作为一个整体读入内存的文件.

      More precisely, ed preserves the file's existing inode, which ensures that all the file's attributes are preserved.
      However, it does not overwrite individual bytes of the existing file, but reads the entire file into a buffer in memory, and writes the entire buffer to the file when asked to.
      This makes ed suitable only for files small enough to be read into memory as a whole.

      相比之下,sed -i(GNUBSD sed),它的 GNU 4.1+ 对应版本,awk -i inplace,以及 perl -i 用一个新创建的替换原始文件,这意味着它们:

      By contrast, sed -i (GNU and BSD sed), its GNU 4.1+ counterpart, awk -i inplace, and also perl -i replace the original file with a newly created one, which implies that they:

      • 销毁符号链接(!) - 如果输入文件是一个符号链接,它会被替换为同名的普通文件
        • 一个很重要的常见场景:假设你的 shell 初始化文件 ~/.bashrc 是一个 符号链接 到你在源代码控制下的其他地方的文件;然后安装一个使用 sed -i 修改 ~/.bashrc 的工具,这会导致它被替换为常规文件,以及指向源代码控制的链接版本已损坏.
        • 更重要的是,BSD sed 的行为甚至会带来安全风险(见下文).
        • destroy symlinks(!) - if the input file was a symlink, it is replaced with a regular file of the same name
          • A common scenario where that matters: say your shell initialization file ~/.bashrc is a symlink to a file elsewhere you keep under source control; you then install a tool that uses sed -i to modify ~/.bashrc, which results in it being replaced with a regular file, and the link to your source-controlled version is broken.
          • What's more, BSD sed's behavior even introduces a security risk (see below).

          他们,然而,

          • 保留扩展属性(如果支持;例如,在 OSX 上)
          • 保留文件权限

          • preserve extended attributes (where supported; e.g., on OSX)
          • preserve file permissions

          • 注意:BSD sed 引入了与 符号链接 相关的安全风险(行为仍然存在于FreeBSD 10 附带的版本):
            • 符号链接的权限被复制到替换文件,而不是符号链接目标的权限.由于默认情况下符号链接获得可执行权限,你总会得到一个可执行文件,无论输入文件是否可执行.
            • Caution: BSD sed introduces a security risk with respect to symlinks (behavior still present as of the version that comes with FreeBSD 10):
              • The symlink's permissions are copied to the replacement file, not the symlink target's. Since symlinks get executable permissions by default, you'll invariably end up with an executable file, whether the input file was executable or not.

              sedgawkperl 可以通过采取额外的步骤来解决上述问题,但是<强>只有保留原始 inode 才能确保的一件事,正如 ed 所做的:

              sed, gawk, and perl could address the issues above by taking extra steps, but there's one thing that can only be ensured if the original inode is retained, as ed does:

              当一个文件被其 inode 编号监控更改时(例如,使用 tail -f),不保留 inode 会破坏监控.

              When a file is being monitored for changes by its inode number (e.g., with tail -f), not preserving the inode breaks that monitoring.

              这篇关于使用 Awk 或 Sed 在特定行的末尾添加语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆