如何将 $PATH 显示为每行一个目录?

Han*_*nkG 65 bash paths

我无法弄清楚如何分别列出各种路径,$PATH使它们看起来像这样:

/bin
/usr/bin
/usr/local/bin
Run Code Online (Sandbox Code Playgroud)

如何才能做到这一点?

hee*_*ayl 82

您可以使用以下任一命令执行此操作,该命令将所有出现的 替换为:新行\n

sed

$ sed 's/:/\n/g' <<< "$PATH"
Run Code Online (Sandbox Code Playgroud)

tr

$ tr ':' '\n' <<< "$PATH"
Run Code Online (Sandbox Code Playgroud)

python

$ python -c 'import sys;print(sys.argv[1].replace(":","\n"))' "$PATH"
Run Code Online (Sandbox Code Playgroud)

  • `tr` 为我工作(在 mac 上,顺便说一句)。谢谢。 (3认同)

Cyr*_*rus 79

使用 bash 的参数扩展

echo "${PATH//:/$'\n'}"
Run Code Online (Sandbox Code Playgroud)

这用换行符 ( )替换 all :in并打印结果。内容不变。 如果您只想替换第一个,请删除第二个斜杠:$PATH\n$PATH
:echo -e "${PATH/:/\n}"

  • 我认为这是最好的解决方案,因为它是在 *pure* bash 中完成的。 (5认同)
  • 按照我的答案中的链接(参数扩展)并向下滚动到名为:`${parameter/pattern/string}` 的最后一个第二部分 (4认同)
  • @DominicCronin:`$'\n'` 的含义见:[ANSI-C Quoting](https://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html) (2认同)
  • 这对我在 ZSH 上有效:`echo "${PATH//:/\n}"` (2认同)

mur*_*uru 30

使用 IFS:

(set -f; IFS=:; printf "%s\n" $PATH)
Run Code Online (Sandbox Code Playgroud)

IFS保存 bash 进行拆分的字符,因此IFSwith:使 bash 拆分$PATHon的扩展:printf在格式字符串上循环参数,直到参数用完。我们需要禁用通配符(通配符扩展),set -f以便 PATH 目录名称中的通配符不会被扩展。

  • 这适用于反斜杠和空格! (2认同)

sou*_* c. 16

使用xargs

xargs -n1 -d: <<< $PATH
Run Code Online (Sandbox Code Playgroud)

man xargs

xargs -n1 -d: <<< $PATH
Run Code Online (Sandbox Code Playgroud)


小智 9

可能唯一没有提到的方法是我多年来一直使用它的方式:

echo $PATH | tr ":" "\n"

因此,在您的 .profile 或 .bash_profile 或其他文件中,您可以添加:

alias path='echo $PATH | tr ":" "\n"'


Ser*_*nyy 7

在这个答案中:

  1. C
  2. Python
  3. 红宝石
  4. 替代awk

1. C

由于已经采用了所有脚本语言,我将使用 C。使用get_env()函数获取环境变量非常容易(请参阅GNU C 库文档)。剩下的就是简单的字符操作

bash-4.3$ cat get_path.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    char *path = getenv("PATH");
    int length = strlen(path) -1;
    for(int i=0;i<=length;i++){
        if (path[i] == ':')
            path[i] = '\n';
        printf("%c",path[i]);
    }
    printf("\n");
    return 0;
}
bash-4.3$ gcc get_path.c
bash-4.3$ ./a.out 
/home/xieerqi/bin
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin
/opt/microchip/xc16/v1.25/bin
/opt/microchip/xc32/v1.40/bin
/opt/microchip/xc8/v1.35/bin
/home/xieerqi/bin
/home/xieerqi/bin/sh
Run Code Online (Sandbox Code Playgroud)

2. 蟒蛇

但也因为“为什么不”,这里是通过命令行参数的替代 python 版本 sys.argv

python -c 'import sys; print "\n".join(sys.argv[1].split(":"))' "$PATH"
Run Code Online (Sandbox Code Playgroud)

3. 红宝石

Ruby 默认不随 Ubuntu 一起提供,这与 C 编译器和 Python 解释器不同,但如果您发现自己在使用它,Ruby 中的解决方案是这样的:

ruby -ne 'puts $_.split(":")' <<< "$PATH"
Run Code Online (Sandbox Code Playgroud)

正如 7stud(非常感谢!)在评论中所建议的,这也可以缩短为

ruby -F: -ane 'puts $F' <<<$PATH
Run Code Online (Sandbox Code Playgroud)

这种方式

ruby -0072 -ne 'puts chomp' <<<$PATH
Run Code Online (Sandbox Code Playgroud)

4.替代awk

我们可以利用split()函数将读取的行分解为数组,并使用for-each循环将每个项目打印在单独的行上。

awk '{split($0,arr,":"); for(var in arr) print arr[var]}' <<< $PATH
Run Code Online (Sandbox Code Playgroud)


Nat*_*man 7

这是 Go 中的等价物:

$ cat path.go
package main

import (
    "fmt"
    "os"
    "strings"
)

func main() {
    for _, p := range strings.Split(os.Getenv("PATH"), ":") {
        fmt.Println(p)
    }
}

$ go run path.go
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin
/home/nathan/.local/bin
/home/nathan/go/bin
Run Code Online (Sandbox Code Playgroud)


ter*_*don 7

这里还有一些方法。我正在使用PATH包含反斜杠、空格甚至新行的with 目录来表明它们应该与任何东西一起工作(除了cut在换行符上失败的那个):

$ echo "$PATH"
/bin:usr/bin/:/usr/local/bin:/some\ horrible thing:/even 
new lines
Run Code Online (Sandbox Code Playgroud)
  • 一些 Perl 方法:

    $ perl -pe 's/:/\n/g' <<<"$PATH"
    /bin
    usr/bin/
    /usr/local/bin
    /some\ horrible thing
    /even 
    new lines
    
    Run Code Online (Sandbox Code Playgroud)

    -p手段“将给出脚本后打印每个输入行-e”。该脚本使用替换运算符 ( s/oldnew/) 将所有内容替换:为换行符。

    $ perl -lne 'print for split /:/' <<<"$PATH"
    /bin
    usr/bin/
    /usr/local/bin
    /some\ horrible thing
    /even 
    new lines
    
    Run Code Online (Sandbox Code Playgroud)

    -l增加了一个新行给每个print呼叫。在这里,脚本正在拆分其输入:,然后循环遍历每个拆分元素并打印它。

    $ perl -F: -ane '$"="\n";print "@F"' <<<"$PATH"
    /bin
    usr/bin/
    /usr/local/bin
    /some\ horrible thing
    /even 
    new lines
    
    Run Code Online (Sandbox Code Playgroud)

    -a品牌perl表现得像awk:它的每一个输入行的它会分裂上由给定的字符-F(因此:,这里)并将结果保存在数组中@F。的$"是一种特殊的Perl变量中,“列表分隔”,其值被打印的打印列表中的每个元件之间。因此,将其设置为换行符将使print @list打印每个元素,@list然后是换行符。在这里,我们使用它来打印@F.

    $ perl -F: -ane 'print join "\n", @F' <<<"$PATH"
    /bin
    usr/bin/
    /usr/local/bin
    /some\ horrible thing
    /even 
    new lines
    
    Run Code Online (Sandbox Code Playgroud)

    与上述相同的想法,只是少打高尔夫球。$"我们没有使用,而是显式地join使用换行符对数组进行操作,然后进行打印。

  • 简单grep的 PCRE 魔法:

    $ grep -oP '(^|:)\K[^:]+' <<<"$PATH"
    /bin
    usr/bin/
    /usr/local/bin
    /some\ horrible thing
    /even 
    new lines
    
    Run Code Online (Sandbox Code Playgroud)

    -o品牌grep只打印每条线的匹配部分,所以每个匹配被打印在单独的行。在-P使Perl兼容的正则表达式(PCRE)。正则表达式正在寻找跟在行 ( ) 或字符开头的非:( [^:]+) 段。这是一个 PCRE 技巧,意思是“丢弃在这一点之前匹配的任何内容”,这里也使用它来避免打印。 ^:\K:

  • 还有一个cut解决方案(这个在换行符上失败,但可以处理反斜杠和空格):

    $ cut -d: -f 1- --output-delimiter=$'\n' <<<"$PATH"
    /bin
    usr/bin/
    /usr/local/bin
    /some\ horrible thing
    /even 
    new lines
    
    Run Code Online (Sandbox Code Playgroud)

    使用的选项是-d:将输入分隔符设置为:-f 1-这意味着打印所有字段(从第一个到结尾)并--output-delimiter=$'\n'设置输出分隔符。这$'\n'ANSI C 引用,是一种在 shell 中打印换行符的方法。

在上述所有示例中,我使用 bash(和其他一些 shell)的here string ( <<<) 运算符将字符串作为输入传递给程序。所以command <<<"foo"相当于echo -n "foo" | command. 请注意,我总是引用"$PATH",如果没有引号,shell 会吃掉换行符。


@7stud评论中给出了另一种方法,太好了,不能不包括:

$ perl -0x3a -l012 -pe '' <<<"$PATH"
Run Code Online (Sandbox Code Playgroud)

这就是所谓的打高尔夫球。将-0输入记录分隔符指定为八进制或十六进制数。这是定义“行”的内容,其默认值是\n换行符。在这里,我们将其设置:x3a十六进制的 a (try printf '\x3a\n')。在-l做了三两件事。首先,它$/从每行的末尾删除输入记录分隔符 ( )——有效地删除了:此处——然后,它将输出记录分隔符 ( $\) 设置为给定的任何八进制或十六进制值 ( 012is \n)。如果$\已定义,则将其添加到每次print调用的末尾,因此这将导致每个print.

-pe意愿p施加由给出的脚本后RINT每个输入行-e。这里没有脚本,因为所有的工作都是由上面描述的选项标志完成的!


Kaz*_*lfe 5

我们需要更多的 Java!

\n\n\n\n
public class GetPathByLine {\n    public static void main(String[] args) {\n        for (String p : System.getenv("PATH").split(":")) {\n            System.out.println(p);\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

将此保存到GetPathByLine.java,并使用以下命令进行编译:

\n\n
javac GetPathByLine.java\n
Run Code Online (Sandbox Code Playgroud)\n\n

运行:

\n\n
java GetPathByLine\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n
\xe2\x94\x8c\xe2\x94\x80[17:06:55]\xe2\x94\x80[kazwolfe@BlackHawk]\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80> ~ $ cat GetPathByLine.java \npublic class GetPathByLine {\n    public static void main(String[] args) {\n        for (String p : System.getenv("PATH").split(":")) {\n            System.out.println(p);\n        }\n    }\n}\n\xe2\x94\x8c\xe2\x94\x80[17:06:58]\xe2\x94\x80[kazwolfe@BlackHawk]\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80> ~ $ javac GetPathByLine.java \n\xe2\x94\x8c\xe2\x94\x80[17:07:02]\xe2\x94\x80[kazwolfe@BlackHawk]\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80> ~ $ java GetPathByLine \n/usr/local/sbin\n/usr/local/bin\n/usr/sbin\n/usr/bin\n/sbin\n/bin\n/usr/games\n/usr/local/games\n/snap/bin\n
Run Code Online (Sandbox Code Playgroud)\n