我正在尝试编写一个 bash 函数,其行为where
类似于tcsh
.在 中tcsh
,where
列出了具有给定名称的所有内置函数、别名和可执行文件的绝对路径PATH
,即使它们被隐藏,例如
tcsh> where tcsh
/usr/bin/tcsh
/bin/tcsh
作为其中的一部分,我想循环遍历其中的所有内容$PATH
,并查看是否存在具有适当名称的可执行文件。
以下 bash 片段旨在循环遍历以冒号分隔的路径列表,并打印每个组件,后跟换行符,但是,它似乎只是将所有内容的全部内容打印$PATH
在一行上
#!/bin/bash
while IFS=':' read -r line; do
printf "%s\n" "$line"
done <<< "$PATH"
按照现在的情况,bash where
只需./where
打印/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
那么,如何设置 while 循环,以便循环变量的值依次是冒号分隔的路径列表的每个段?
答案1
read
用于分隔它读取的行中的单词,直到其中的任何字符第一次出现时才IFS
告诉读取。read
IFS=: read -r a b
将读取一行,将第一部分之前的部分放入:
,$a
并将其余部分放入$b
。
IFS=: read -r a
会将整行(其余部分)放入$a
(除非该行仅包含一个字符:
并且它是该行的最后一个字符)。
如果你想读到第一个:
,你可以使用read -d:
(ksh93
,zsh
或bash
仅)。
printf %s "$PATH" | while IFS= read -rd: dir || [ -n "$dir" ]; do
...
done
(我们没有使用<<<
as 来添加额外的换行符)。
或者您可以使用标准分词:
IFS=:; set -o noglob
for dir in $PATH""; do
...
done
现在请注意一些警告:
- 空
$PATH
组件表示当前目录。 - 空
$PATH
表示当前目录(即$PATH
包含一个当前目录的组件,因此while read -d:
在这种情况下循环将是错误的)。 //file
/file
与某些系统上的情况不同,因此如果$PATH
包含/
,则需要小心诸如 之类的事情$dir/$file
。- 一个未设置$PATH 表示默认要使用搜索路径,它与设置但空的 $PATH 不同。
现在,如果它仅相当于tcsh
/zsh
的where
命令,您可以使用bash
's type -a
。
更多阅读:
答案2
相反,请使用awk
、 或tr
、 甚至sed
。
printf %s\\n "$PATH" | tr ':' '\n'
printf %s "$PATH" | awk 'BEGIN {RS=":"}; 1'
或者,由于这是您正在处理的 shell 变量,因此只需使用bash
模式替换:
echo "${PATH//:/
}"
(看LESS=+/parameter/pattern man bash
。)
答案3
纯粹bash
,它与通配符的第二种方法,但这是一行:
echo -e "${PATH//:/"\n"}"
答案4
外壳实用程序:
echo $PATH | tr ':' '\n'