如何使用 sed 命令将 /home/user 替换为 ~

如何使用 sed 命令将 /home/user 替换为 ~

假设这是以下的输出pwd

/home/amarakon/.local/src/amarakon/scripts/src

我怎样才能把它改成这样:

~/.local/src/amarakon/scripts/src

我尝试了这个命令:

pwd | sed 's|/home/.*|~|'

但这是输出:

~

答案1

如果使用zsh,您可以使用:

print -P '%~'

要获取当前工作目录,并将主目录替换为~.如果是主目录并且之前已经扩展过,它也将替换/home/directory/of/otheruser为。~otheruser/home/directory/of/otheruserotheruser~otheruser

您通常会输入%~your$PROMPT来获取当前工作目录。选项启用该内置功能的快速扩展-Pprint

也可以使用参数扩展%标志在参数扩展时进行提示扩展:

printf '%s\n' ${(%):-%~}

~也可以使用参数扩展标志启用该替换D,因此您也可以执行以下操作:

printf '%s\n' ${(D)PWD}

您也可以手动完成:

set -o extendedglob
printf '%s\n' ${PWD/#%(#b)$HOME(|\/*)/\~$match[1]}

但请注意,如果$HOME有符号链接或.路径组件,或者$PWD有符号链接组件,则可能无法正常工作,因为您最终会得到包含不同家庭表示形式的变量。

sed如果想要对 的任意值执行此操作会很麻烦$HOME。你需要/首先是转义和正则表达式运算符.作为正则表达式运算符,在用户名中很常见),在语言C环境中执行此操作,因为 dir 路径不能保证是文本,将所有行加载$PWD到模式空间中,仅在开头且仅在后跟时进行替换/或主题的结尾:

escaped_HOME=$(printf '%s\n' ~ | LC_ALL=C sed '
  :1
  $!{
    N
    b1
  }
  s:[][\\/.^$*]:\\&:g
  s/\n/\\n/g'
)
pwd | LC_ALL=C sed '
  :1
  $!{
    N
    b1
  }
  s/^'"$escaped_HOME"'\(\(\/.*\)\{0,1\}\)$/~\1/'

不是最好的工具。和perl

perl -MCwd -le 'print getcwd =~ s|^\Q$ENV{HOME}\E(?![^/])|~|r'

如果$HOME是,/对于某些系统用户来说通常是这样,%~不会/~“或”替换“/dir哪个~/dir”可能也不错。手动的将替换/~,但不是/dir~/dir认为可以接受的。

答案2

正如其他人所说,替换任何匹配项/home/.*都会~替换您显示的示例中的整个字符串,因为.*匹配到字符串的最末尾。

该变量PWD还将保存当前目录的路径,我们可以使用很多该值的更便宜的参数替换:

[[ "$PWD/" == "${HOME%/}/"* ]] && printf '~%s\n' "${PWD#"${HOME%/}"}"

这测试是否$PWD包含$HOME在开始处,如果是,则打印$PWD该部分替换为~。这要快得多,因为它不需要昂贵的(运行相对较慢)的外部实用程序。

更便携:

case $PWD/ in ("${HOME%/}/"*) printf '~%s\n' "${PWD#"${HOME%/}"}"; esac

答案3

.匹配任何字符,因此它将匹配该行中剩下的所有内容,包括后面的斜杠和路径部分。

您基本上希望将模式的该部分限制为一系列不是斜杠的内容,因此当遇到斜杠时(如果遇到斜杠),它会停止替换:

pwd | sed 's|/home/[^/]*|~|'

如果您有在根文件夹之外命名的子文件夹,您可能会考虑要求'/home'位于开头:home

pwd | sed 's|^/home/[^/]*|~|'

这应该适用于 pwd 的输出,但如果您在较长的字符串中将 $HOME 替换为 ~ ,您可能会保留第一种方式。

答案4

我知道这是一个老问题,但您可以使用字符串运算符来实现此目的:

$ pwd
/home/kali/Documents
$ [ -z "${PWD%%$HOME*}" ] && echo ${PWD/$HOME/'~'} || echo $PWD
~/Documents

$ pwd
/etc/systemd/network
$ [ -z "${PWD%%$HOME*}" ] && echo ${PWD/$HOME/'~'} || echo $PWD
/etc/systemd/network

$ pwd
/tmp/home/kali/Documents
$ [ -z "${PWD%%$HOME*}" ] && echo ${PWD/$HOME/'~'} || echo $PWD
/tmp/home/kali/Documents

现在,您特别询问了sed,我认为它不是最好的工具,甚至不是必要的,但您会这样做:

$ pwd | sed "s|^$HOME|~|"
~/Documents

相关内容