问题
我在 Termux 上,在 Termux 上它不是/usr
,而是/data/data/com.termux/files/usr
。
当运行未考虑 Termux 设计的脚本(主要是 bash 和 make)时,这有时会导致问题。
我的意图
每当脚本想要打开从 开始的路径中的文件时/usr
,我希望将其“重写”为有效路径。
任何解决该问题的解决方案也受到欢迎。
答案1
简单的答案是“用于sed
更改脚本中所有出现的/usr
to ”。/data/data/com.termux/files/usr
例如
sed -i -e 's=/usr=/data/data/com.termux/files/usr=g' *.sh
这样做的问题是:如果部分或全部路径/usr
已经更改为/data/data/.../usr
,那么它们将再次更改,最终为/data/data/com.termux/files/data/data/com.termux/files/usr
。例如
$ echo /usr | sed -e 's=/usr=/data/data/com.termux/files/usr=g'
/data/data/com.termux/files/usr
$ echo /data/data/com.termux/files/usr | sed -e 's=/usr=/data/data/com.termux/files/usr=g'
/data/data/com.termux/files/data/data/com.termux/files/usr
要解决此问题,仅当 /usr 前面有空格或行开头时才允许更改:
$ echo /data/data/com.termux/files/usr | sed -e 's=\(^\|[[:space:]]\)/usr=\1/data/data/com.termux/files/usr=g'
或者使用扩展正则表达式稍微更具可读性:
$ echo /data/data/com.termux/files/usr | sed -E -e 's=(^|[[:space:]])/usr=\1/data/data/com.termux/files/usr='
/data/data/com.termux/files/usr
以下是在我记得后视是不必要的之前写的(IMO,这是一个“更好”更普遍有用的解决方案,但不是必需的)....留下来主要是因为它是有用的信息,而我不这样做想要删除它:
或者,您可以使用称为“负向后查找”的正则表达式功能。不幸的是,sed 不支持look-behinds 或look-aheads(*)。
Perl 确实支持环视,因此如果您随 Termux 安装了 perl,则可以使用它(自从我上次使用 termux 以来已经很长时间了,所以我不记得它是否包含基础 perl。它是当然是一个可安装的包)。例如
perl -i -p -e 's=(?<!/data/data/com.termux/files/)/usr=/data/data/com.termux/files/usr=g' *.sh
(顺便说一句,使用它的-p
选项,perl 的工作方式与 sed 类似,作为修改标准输入或文件的工具。使用它的-n
选项,perl 的工作方式与 类似sed -n
。这是有意为之的 - perl 的这种用法旨在成为类似 sed 的直接替代品工具通过 Perl 的全部功能得到增强)。
或者,负后视可以避免更改 /usr,如果任何字母数字或/
字符紧接在 之前/usr
:
perl -i -p -e 's=(?<![[:alnum:]/])/usr=/data/data/com.termux/files/usr=g' *.sh
您可以在下面看到 /usr 仅在其自身时才会更改:
$ echo /usr | perl -pe 's=(?<![[:alnum:]/])/usr=/data/data/com.termux/files/usr=g'
/data/data/com.termux/files/usr
$ echo /data/data/com.termux/files/usr | perl -pe 's=(?<![[:alnum:]/])/usr=/data/data/com.termux/files/usr=g'
/data/data/com.termux/files/usr
$ echo /foo/bar/usr | perl -pe 's=(?<![[:alnum:]/])/usr=/data/data/com.termux/files/usr=g'
/foo/bar/usr
(*) 据我所知,唯一支持环视的 sed 版本是 Super Sed 或ssed(主页目前无法使用)。ssed
似乎是废弃软件,并且已经很多年没有更新了 - 它基于 1998 年的 GNU sed 3.02,而当前的 GNU sed 是 2020 年的 4.8 版本。 ssed
为 Debian 打包,因此可能也可用于 Termux。但如果你要安装它,你也可以只使用 perl。
无论如何,ssed
有一个-R
选项允许它使用 Perl 兼容的正则表达式,聚合酶链式反应。
$ echo /data/data/com.termux/files/usr | ssed -R 's=(?<![[:alnum:]/])/usr=/data/data/com.termux/files/usr='
/data/data/com.termux/files/usr
$ echo /foo/bar/usr | ssed -R 's=(?<![[:alnum:]/])/usr=/data/data/com.termux/files/usr='
/foo/bar/usr