【问题标题】:How to edit file content using zsh terminal?如何使用 zsh 终端编辑文件内容?
【发布时间】:2015-05-08 18:17:13
【问题描述】:

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

echo 'Hello, world.' >hello.rb

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

我希望能够严格更改文件hello.rb 通过使用我的 zsh 终端,这可能吗?

【问题讨论】:

  • 你不想使用 TextEdit,所以没有实际的 OSX 应用程序(我猜你正在使用 OSX),但是 vimnano 呢?只需输入vim hello.rbnano hello.rb,您就可以在终端中编辑该文件。如果您以前没有使用过vim,后者可能更容易。
  • 根据问题和描述,我确信要避免使用文本编辑器,并且只有终端中的 shell 才是目标。

标签: terminal zsh


【解决方案1】:

Zsh 不是终端,而是外壳。终端是 shell 执行的窗口。 shell 是提示您命令并执行它们的文本程序。

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

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

autoload zed

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

zed hello.rb

(退出并使用Control-j保存)

【讨论】:

  • zed 命令似乎无法识别,当我输入它时它是红色而不是绿色
  • 确实,您需要autoload zed。编辑我的答案来解决这个问题。
  • 需要明确的是,zed 是 zsh 工具集合的一部分,但它是一个像 vim 或 vi 或 ex 或 edlin 一样的编辑器,所以从技术上讲,仍然不能从终端在 zsh 中编辑.但是对于如何使用 zsh 从终端使用文本编辑器的问题,绝对 +1 是一个很好的答案。我希望这很快成为问题。 :)
  • @gvoff: zed 是一个 zsh 函数包装 vared 这是一个 zsh 内置命令(执行一次后见 which zedwhich vared)。这一切都发生在 zsh 中,不涉及外部进程(在执行 zed 时请参阅 pstree)。根本不是“实际上就像vim
  • 我明白了。我知道它是可用的,但一直认为它是一个行编辑器,与 zsh 一起分发,而不是内置的包装器。这部分问题肯定回答了如何从 shell 进行编辑。
【解决方案2】:

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

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

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

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

在这里,我使用方便的mapfile 模块,因为我可以逐字节加载文件的内容。或者,您可以使用 % Buffer="$(<path/to/file)",就像 zed 一样,但您总是会删除尾随的换行符,并且由于拼写错误或环境变化可能会进行其他分词,因此模块方法的简单性是最好的。完成后,您只需将 $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") 在给定索引之后插入新行。要么将所有后续元素(包括完全空的元素)调整为当前索引加一。

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

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

【讨论】:

    【解决方案3】:

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

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

    例如

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

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

    当然,通过您对“更改”文件的使用和定义进行编辑,这是使用 shell 执行此操作的最简单方法。

    通常情况下,您可能想使用终端编辑器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-11
      • 2016-06-12
      相关资源
      最近更新 更多