如何使用 zsh 终端编辑文件内容?

How to edit file content using zsh terminal?

我在 zsh 上创建了一个空目录并添加了一个文件 通过执行以下操作调用 hello.rb:

echo 'Hello, world.' >hello.rb

如果我想使用终端对此文件进行更改 不打开文件的正确方法是什么 本身使用比方说 TextEditor?

我希望能够严格地在文件中进行更改hello.rb 通过使用我的 zsh 终端,这完全可行吗?

您已经创建并编辑了文件。

要再次编辑,可以使用>>追加。

例如

echo "\nAnd you too!\n" >> hello.rb

这将通过连接附加字符串来编辑文件。

编辑,当然是通过你使用和定义'changing'一个文件,这是最简单的方法,使用shell.

以正常方式,尽管您可能想使用终端编辑器。

Zsh 不是终端而是 shell。终端是执行 shell 的 window。 shell 是提示您命令并执行它们的文本程序。

如果您想在终端中编辑文件,那么使用 vimnanoemacs -nw 或任何其他文本模式文本编辑器即可。它们不是 Zsh 命令,而是您可以从 Zsh 或任何其他 shell.

调用的外部命令

如果您想在 Zsh 中编辑文件,请使用 zed。您将需要 运行 一次(在 ~/.zshrc 中)

autoload zed

然后您可以编辑 hello.rb 使用:

zed hello.rb

(退出并保存 Control-j

Zed 是一个很好的答案,但要更加精简 - 对于甚至脚本也可以进行的编辑级别 - zsh 可以处理变量中的所有 256 characters/byte-values(包括 null)。这意味着您可以直接从命令行逐行或逐块编辑几乎任何类型的文件数据。这大约是 zed/vared 所做的。如果您的当前版本包含所有标准模块,那么加载 zsh/mapfilezsh/system 将是一个很大的好处,这样您就可以捕获命令扩展遗漏的任何字符 ( zed 使用 $(<$file) 将文件读入内存)。这是您可以使用此变量操作方法的示例:

% typeset -T Buffer buffer $'\n'
% typeset -T Edit edit $'\n'

最常见的做法是使用换行符来分隔要编辑的文本文件。 这个方便的功能将使 zsh 一次可以完全访问一行或一系列行,而不会无意中弄乱数据。

% zmodload zsh/mapfile
% Buffer=$mapfile[path/to/file]

在这里,我使用方便的 mapfile 模块,因为我可以逐字节加载文件的内容。或者,您可以像 zed 一样使用 % Buffer="$(<path/to/file)",但您始终会删除尾随的换行符,并且由于打字错误或环境变化,可能会出现其他单词拆分,因此模块方法的简单性是最好的。完成后,您只需将 $Buffer 值分配回 $mapfile[file] 或使用更经典的命令,如 printf '%s' $Buffer >path/to/file 来保存更改(这是精确的字符串写入,逐字节,所以你添加回来的任何换行符或格式都会被写入。

您使用映射数组在 Buffer 和 Edit 之间传输行,但请记住,在最简单的形式中,将一个数组分配给另一个数组会丢弃完全为空的元素(one \n \n two \n three 变为 one \n two \n three).如果使用整个数组,您可以通过引用输入数组并将“@”符号添加到其索引 "$buffer[@]" 来抑制此空元素删除;如果使用数组 "${(@)buffer[2,50]}" 的范围,则将“@”符号添加到标志中。保留空行对于打字来说可能有点麻烦,但是这些多个数组应该只在脚本或函数中使用,因为您可以从命令行使用 buffer[54]="echo This is a newly written line."

一次只编辑一行
% edit=($buffer[50,70])
...
% buffer[50,70]=($edit)

这是标准的 Zsh 语法,这意味着在 ... 区域中,您可以随意编辑和操作 $edit 行数组或 $Edit 标量文本块,包括添加更多行或删除一些行。当您将行添加回 $buffer 时,它将用新行替换指定的行块 (50-70),自动扩展或减少其他数组元素以容纳重新整合的行。 -- 由于动态数组的适应性,您也可以像这样 buffer[40]=("new string as new line" "$buffer[40]") 插入任何您需要的作为新行的内容。这会将它插入到给定的索引之前,而交换元素的顺序 ("$buffer[40]" "new string as new line") 会将新行插入到给定的索引之后。 Either 会将所有后续元素(包括完全空的元素)调整为其当前索引加一。

如果您想重写 zed 函数以以某种复杂的方式使用此方法,例如:newzed /path/to/file [start-line] [end-line],那也很好用。

在我离开之前,我想提一下,直接使用 vared,一旦你在交互式终端上输入了这些命令,你可能会感到沮丧,因为你不能使用 "Enter"插入或附加新行。我发现我的终端和使用 ESC-ENTER 的 Zsh 版本运行良好,但我不知道旧版本(Mac 通常有一个不是最新的版本,如果我没记错的话)。如果这不起作用,您可能需要进行一些文档挖掘以了解如何设置 ZLE(Zsh 行编辑器,Zsh 的一个组件)或获取更新版本的 Zsh。此外,其他一些 shells,在索引标量变量时可能按字节计数,因为在 ascii 和 C 中,字节与字符相同,但 Zsh 支持 UTF8 并将按 UTF8 字符索引标量字符串,除非您关闭 shell 选项 multibyte(默认情况下打开)。如果您需要使用旧的字节字符索引,这将有助于处理每一行。另外,如果你的 Zsh 版本不是用 zsh/mapfilezsh/system 编译的,那么你可以使用 read 内置选项的数量来达到类似的效果,比如 <path/to/file |read -u 0 -k $[5 * 2**20] -r -s Buffer ||(($#Buffer)).正如您在这里看到的,您必须使读取长度足够大以适应文件的大小,否则它将遗漏部分文件,并且 read return 代码几乎总是错误的,因为无法读取字符串的全长。我们用 ||(($#Buffer)) 解决了这个问题,但是这个内置函数根本就不是为了有效地处理大规模字节操作,所以你所看到的就是你能从中得到的。