mac zsh

    技术2024-06-09  81

    关于本系列

    典型的UNIX®管理员经常使用一系列重要的实用程序,技巧和系统,以协助管理过程。 有一些关键实用程序,命令行链和脚本可用来简化不同的过程。 这些工具中的一部分随操作系统一起提供,但是大多数技巧来自多年的经验以及减轻系统管理员生活的渴望。 本系列的重点是从各种不同UNIX环境中的可用工具中获取最大收益,包括简化异构环境中管理的方法。

    zsh背景

    UNIX和Linux®下的Shell通常根据UNIX最早版本附带的原始Shell分为两类之一。 两种类型是Bourne外壳和C外壳; 后者之所以与众不同,是因为其格式和结构类似于C编程语言。

    Bourne Shell比C Shell更易于使用和理解,但是对于您可能希望在Shell编程环境中实现的复杂脚本编程而言,它不那么实用。 Korn shell提供了Bourne shell的易用性,并添加了作业控制扩展(允许您轻松管理多个后台作业),命令行编辑和历史记录,并添加了C shell的元素以简化编程。

    Z Shell(zsh)在设计时考虑了交互使用而不是编程,因此它合并了许多功能,使使用和运行命令变得更加容易。 示例包括更广泛的文件名匹配(globbing),用于重定向输入和输出的多个I / O流以及完全可自定义的命令行完成系统。

    文件名生成

    文件名遍历是将文件名或文件规范转换为文件列表以供命令行使用的过程,例如,在复制或移动文件时。 基本的文件名通配符包括?的使用。 表示单个字符,或*表示一个或多个字符。

    例如,要列出所有C源文件,可以使用清单1 。

    清单1.列出所有C源文件
    $ ls *.c barney.c betty.c fred.c wilma.c

    而且,您可以使用字母集合(例如,可以在正则表达式中使用)来列出扩展名为“ c”或“ o”的文件,如清单2所示。

    清单2.列出扩展名为“ c”或“ o”的文件
    $ ls *.[co] barney.c betty.c fred.o barney.o fred.c wilma.c

    使用zsh,可以使用相同的通配符,但是您也可以将扩展的globing用于其他选项。 要打开扩展glob,请设置EXTENDEDGLOB环境变量,或使用: $ setopt extendedglob 。

    现在,您可以使用诸如^字符之类的结构来显示所有与给定文件规范不匹配的文件。 例如,要列出与* .c规范不匹配的所有文件,请使用清单3 。

    清单3.列出与* .c不匹配的文件
    zsh$ ls ^*.c barney.o betty.h fred.h fred.o

    表达式<xy>匹配整数范围。 例如,如果您使用日期归档了访问日志,则可以选择特定日期范围内的所有文件。 为此,请使用年,月和日的顺序命名文件,并使用零填充值。 例如,要列出2006年11月3日至10日之间的日志,可以使用清单4 。

    清单4.列出2006年11月3日至10日之间的日志
    zsh$ ls access<20061103-20061110>.log access20061103.log access20061106.log access20061109.log access20061104.log access20061107.log access20061110.log access20061105.log access20061108.log

    您还可以使用类似正则表达式的组来匹配文件。 例如,使用清单5列出所有名为fred和barney的文件。

    清单5.列出所有fred和barney文件
    zsh$ ls (fred|barney)* barney.c fred.c fred.o barney.o fred.h

    也可以使用** /来搜索子目录。 该过程是递归的,例如find命令,因此您可以产生与find命令等效的过程,例如$ find . -name "*.c" $ find . -name "*.c" 。

    在zsh(具有扩展的globing)中,可以将其扩展为: zsh$ ls **/*.c 。

    或者,您可以结合其他示例,例如使用清单6中的命令在子目录中找到所有C源代码和已编译的目标文件。

    清单6.查找所有C源代码和已编译的目标文件
    zsh$ ls **/*.(c|o) glob/barney.c glob/betty.c glob/fred.o glob/barney.o glob/fred.c glob/wilma.c

    最后,zsh支持许多后缀限定符。 要获取可执行文件的列表,请在globlob表达式的末尾使用后缀修饰符(*)(请参见清单7 )。

    清单7.获取可执行文件列表
    zsh$ ls *(*) barney fred

    您还可以在全局表达式的末尾使用(x)获得可执行文件的列表(请参见清单8 )。

    清单8.使用(x)获得可执行文件列表
    zsh$ ls *(x) barney fred

    上面列出的文件可由文件所有者执行。 大写的X选择其他人可执行的文件。 文件上的R / r(可读)和W / w(可写)模式也是如此。

    命令或进程替换

    在大多数Shell环境中,您可以使用基本的进程替换将一个命令的输出嵌入另一个命令的输入或参数中。 您可以使用backtick运算符执行此操作(请参见清单9 )。

    清单9.使用backtick运算符执行流程替换
    $ emacs `find . -name "*.html"`

    zsh中有许多可用的选项。 主要方法是使用$()构造。 这提供了反引号的直接替代方法,并且具有在某些命令组合中更容易嵌入和嵌套的优点。 例如,您可以将清单9重写为清单10 。

    清单10.使用反引号执行流程替换的替代方法
    zsh$ emacs $(ls **/*.html)

    在这里,进程替换运行目录列表组件,并返回文件名列表,该文件名又提供给emacs命令的参数列表。

    另一个有用的构造是=(list)结构。 使用此功能时,括号中的元素会生成一个临时文件,并返回此文件的名称。 例如,您可以使用清单11生成文本文件。

    清单11.生成文本文件
    zsh$ cat =(print -l tom dick harry) tom dick harry

    更有用的是,您可以将其与其他元素结合起来以支持更复杂的输出和过滤。 例如,您可以使用以下命令获得与imapd和httpd匹配的进程的列表(IMAP邮件服务和Apache http服务)(请参见清单12 )。

    清单12.获取与imapd和httpd匹配的进程的列表
    zsh$ ps -ax |fgrep -f =(print -l httpd imapd) 406 ?? Ss 0:02.05 /usr/sbin/httpd 426 ?? S 0:01.32 /usr/sbin/httpd 429 ?? S 0:06.42 imapd: sulaco.mcslp.pri [192.168.0.101] appleblog user.appleblog 434 ?? S 0:57.81 imapd: sulaco.mcslp.pri [192.168.0.101] mcarc user.mcarc 435 ?? S 0:00.14 imapd: sulaco.mcslp.pri [192.168.0.101] mlists user.mlists 436 ?? S 0:00.12 imapd: sulaco.mcslp.pri [192.168.0.101] play user.play 437 ?? S 0:01.16 imapd: sulaco.mcslp.pri [192.168.0.101] mc user.mc 507 ?? S 0:01.25 /usr/sbin/httpd

    在清单12中 , print命令将每一行的每个参数打印到一个临时文件中。 然后,文件由fgrep用作与进程列表匹配的列表。 命令完成后,将删除临时文件。

    因为该功能从输出创建了临时文件,所以您可以使用它来执行以前需要创建临时文件并自己删除的功能和序列。 例如,要比较两个不同目录之间的文件列表,可以将每个目录中的文件列表输出到一个临时文件,然后使用diff命令比较输出。 使用zsh,可以在单个命令行上实现相同的结果(请参见清单13 )。

    清单13.比较两个不同目录之间的文件列表
    zsh$ diff =(ls new) =(ls old) 3d2 < barney.o 9d7 < fred.o

    在此示例中,两个替换的ls命令生成一个临时文本文件,然后由diff命令对其进行内联diff 。

    多个I / O流

    与过程替换系统相关的是更广泛的重定向系统。 在大多数Shell中,您习惯于在文件之间来回重定向(请参见清单14 )。

    清单14.在文件之间重定向
    $ crontab <newtab $ ls > filelist

    您可以使用zsh同时重定向到多个输出(请参见清单15 )。

    清单15.同时重定向到多个输出
    zsh$ ls >listone >listtwo

    您还可以从多个流中输入(请参见清单16 )。

    清单16.从多个流中输入
    zsh$ sort <listone <listtwo

    管道是隐式重定向,因此它的工作方式几乎相同。 例如,在任何shell中,都可以使用tee命令来重定向文件和标准输出(请参见清单17 )。

    清单17.使用tee命令重定向文件和标准输出
    $ ls | tee listone barney barney.c barney.o betty.c betty.h fred fred.c fred.h fred.o wilma.c

    您可以在zsh中使用清单18 。

    清单18.重定向到zsh中的文件和标准输出
    zsh$ ls >fileone |cat barney barney.c barney.o betty.c betty.h fileone fred fred.c fred.h fred.o wilma.c

    作为流程替换的扩展,您还可以使用<(list)和>(list)构造在另一个命令之间来回重定向(请参见清单19 )。

    清单19.使用<和>在另一个命令之间重定向
    zsh$ sort <(ls) <(ls /usr) X11R6 barney barney.c barney.o betty.c betty.h bin fileone fred fred.c fred.h fred.o include lib libexec local sbin share standalone wilma.c

    在清单19中 ,您将两个ls命令的输出组合为sort命令的标准输入, sort命令从两个不同的目录输出经过组合和排序的文件列表。

    此操作的典型用途是使用剪切和粘贴将字段从文件提取并重组到另一个文件中。 您可能会使用许多带有普通shell的临时文件(请参见清单20 )。

    清单20.使用临时文件将字段从一个文件提取并重组到另一个文件
    $ cut -f1 fileone >t1 $ cut -f5 filetone >t5 $ paste t1 t5

    在zsh中,可以通过跳过临时文件来完成此操作,如清单21所示。

    清单21.剪切并粘贴以从zsh中的文件提取和重组字段
    zsh$ paste -d: <(cut -d: -f1 /etc/passwd) <(cut -d: -f5 /etc/passwd)

    此外,由于可以轻松地嵌套重定向替换,因此您可以创建复杂的结构,例如以与源不同的顺序组合passwd文件中的两个字段,删除注释,然后对其进行排序(请参见清单22 )。

    清单22.在zsh中创建复杂的结构
    zsh$ sort <(egrep -v '^#' <(paste -d: <(cut -d: -f5 /etc/passwd) <(cut -d: -f1 /etc/passwd) ) ) :# mode. At other times this information is handled by one or more of Amavisd User:amavisd Apple Events User:eppc Application Owner:appowner Application Server:appserver ... Xgrid Agent:xgridagent Xgrid Controller:xgridcontroller sshd Privilege separation:sshd

    您可以通过查看清单23中的每个元素来简化清单22 。

    清单23.简化的过程
    - <(cut -d: -f1 /etc/passwd) - Get the first field - <(cut -d: -f5 /etc/passwd) - Get the fifth field - <(paste -d: <(f5) <(f1) ) - Recombine them in a different order - <(egrep -v '^#' <(paste...) - Remove the comments - sort <(egrep ...) - Sort the standard input

    文件和命令完成

    在某些外壳程序(包括zsh)中,可以通过按TAB键完成文件或命令。 让我们以当前目录为例(参见清单24 )。

    清单24.当前目录清单
    zsh$ ls barney betty.c fred fred.o barney.c betty.h fred.c wilma.c barney.o fileone fred.h

    完成后,您可以输入文件名的开头: zsh$ cd bar 。 然后按TAB键并获得全部或部分完成: zsh$ cd barney 。

    再次按TAB键 ,将显示可用文件列表(请参见清单25 )。

    清单25.获取可用文件列表
    zsh$ cd barney barney* barney.c barney.o

    同样的完成过程也适用于目录和路径。 zsh在完成方面还有进一步的技巧。

    定制完成

    标准形式的完成限制在于,当您在命令行上输入文件和路径时,它仅能完成文件和路径(包括命令)。 但是,在许多其他区域中,您可能希望能够完成命令而不必完成所有键入操作。 例如,源代码控制系统Subversion除了提供其他参数以外,还提供了许多您键入的辅助命令。 例如,要将更改提交回Subversion存储库,请使用commit命令: $ svn commit 。 或者,要更新,请使用update命令: $ svn update 。

    但是您必须手动输入。 通过使用zsh中的定制完成控件,您可以将这些子命令添加到svn作为完成过程的一部分。 完成控制是一个非常复杂(有时会造成混淆)的系统,但是基本原理相当容易理解。

    完成是通过许多命令来控制的,但是主要命令是compctl 。 这为基本完成提供了一个简单的界面。 补全可以全局应用(换句话说,就像文件和路径一样),也可以应用于特定命令。

    有许多选项和格式可用,但是为了延续Subversion的想法,您可以使用-k选项来提供一系列单词,这些单词可以作为svn命令的潜在svn (请参见清单26 )。

    清单26.使用-k选项
    zsh$ compctl -k '(commit checkout update status)' svn

    现在,在命令开头键入svn时,需要按TAB键完成命令(请参见清单27 )。

    清单27.按TAB完成命令
    zsh$ svn com <TAB> zsh$ svn commit

    完成系统包括标准功能和完成-例如,在系统,主目录,主机,网络等上查找有效用户。 您也可以自己添加和扩展这些内容,以生成自定义的完成结果。

    例如,您可以创建一个名为activeusers的自定义函数,该函数从users命令返回输出: zsh$ function activeusers { reply =(`users`) } 。

    现在,您可以将其用作其他命令的完成,例如chat: zsh$ compctl -K activeusers chat 。

    现在,当您在命令行上输入chat时,您将获得一个完成列表,该列表仅返回当前登录用户的列表。

    定制完成系统的可用选项和可能性太多,涉及面太广。 请参阅相关主题有关可用选项的官方文档。

    摘要

    zsh包含一系列旨在简化用户与shell环境之间的交互的功能。 扩展包括替代命令以及将信息重定向到不同进程的更好方法。 仅这些选项就使您能够将另一个Shell中需要的许多命令转换为zsh中的单个命令行条目。

    zsh与其他Shell之间的真正区别(甚至包括bash这样的shell中提供的最新改进)是能够自定义自动补全系统,使其不仅可以处理文件名和路径。 扩展功能以支持现有命令的附加参数只是一个示例,但是系统非常灵活,几乎可以完成任何命令或命令行元素。


    翻译自: https://www.ibm.com/developerworks/aix/library/au-satzsh.html

    Processed: 0.015, SQL: 9