bash - How do you load bash_profile for bash commands run from perl script?
问题描述
I wrote simple command that lets me run the last N commands from terminal history. It looks like this: $> r 3
which will replay the last 3 commands.
I have the following alias in my bash profile:
alias r="history -w; runlast $1"
And then the following simple perl script for the runlast
command:
#!/usr/bin/env perl
use strict;
use warnings;
my $lines = $ARGV[0] || exit;
my @last_commands = split /\n/,
`bash -ic 'set -o history; history' | tail -$lines`;
@last_commands =
grep { $_ !~ /(^r |^history |^rm )/ }
map { local $_ = $_; s/^\s+\d+\s+//; $_ }
@last_commands;
foreach my $cmd (@last_commands) {
system("$cmd");
}
This works but my bash profile has aliases and other features (e.g. color output) I want the perl script to have access to. How do I load the bash profile for perl so it runs the bash commands with my bash profile? I read somewhere that if you "source the bash profile" for perl you can get it to work. So I tried adding source ~/.bash_profile;
to my r
command alias but that didn't have an effect. I'm not sure if I was doing that correctly, though.
解决方案
系统派生出一个运行 shell 的进程,该进程是非登录和非交互的;所以没有初始化完成,你没有别名。另请注意,使用的 shell 是/bin/sh
,它通常是指向另一个 shell 的链接。这通常bash
但并非总是如此,因此请bash
明确运行。
为了避免这种情况,您需要使用别名来获取文件,但正如bash
手册页所说
当 shell 不是交互式时,别名不会展开,除非 expand_aliases shell 选项使用 shopt 设置(参见下面 SHELL BUILTIN COMMANDS 下的 shopt 描述)。
因此,如上所述,您需要shopt -s expand_aliases
。但是还有另一个问题:在同一条物理线路上,别名尚不可用;所以它不会像这样在单行中工作。
我还建议将别名放在 中.bashrc
,或者放在一个单独的文件中。
解决方案
添加
shopt -s expand_aliases
到您的~/.bashrc
, 并在定义别名之前(或获取它们的文件),并bash
作为登录 shell运行system('/bin/bash', '-cl', 'source ~/.bashrc; command');
哪里
-l
是--login
.在我的测试中
source ~/.bashrc
,不需要;但是,手册页说当 bash 作为交互式登录 shell 或作为带有 --login 选项的非交互式 shell 调用时,它首先从文件
/etc/profile
中读取并执行命令(如果该文件存在)。读取该文件后,它会按顺序查找~/.bash_profile
、~/.bash_login
和~/.profile
,并从第一个存在且可读的文件中读取并执行命令。并继续指定
~/.bashrc
在非登录的交互式 shell 运行时读取的内容。所以我添加了明确的采购。在我的测试中,在不作为登录 shell 运行时采购
.bashrc
(shopt
添加)不起作用,我不知道为什么。这有点重手。此外,从脚本运行初始化可能是不可取的。
源
~/.bashrc
并发出shopt
命令,然后在命令前换行system('/bin/bash', '-c', 'source ~/.bashrc; shopt -s expand_aliases\ncommand');
真的。有用。
最后,这有必要吗?它自找麻烦,而且可能有更好的设计。
其他的建议
反引号(qx)是上下文感知的。如果在列表上下文中使用它——例如,它的返回分配给一个数组——那么命令的输出将作为行列表返回。当您将它用作参数时,
split
它在标量上下文中,当所有输出都以一个字符串返回时。就放下split
my @last_commands = `bash -ic 'set -o history; history $lines`;
我也
history N
用来获取最后N
一行的地方。在这种情况下,换行符会保留。history N
返回N
历史的最后几行,因此无需管道last
map
可以在不更改原始内容的情况下完成a 中的正则表达式替换map { s/^\s+\d+\s+//r } @last_commands;
使用
/r
修饰符,s///
运算符返回新字符串,而不是更改原始字符串。从 v5.14开始提供这种“非破坏性替换”不需要
$_
在最后明确使用grep
,也不需要在正则表达式中使用括号grep { not /^r |^history |^rm ?/ } ...
或者
grep { not /^(?:r|history|rm)[ ]?/ } ...
现在需要括号的地方,但因为它仅用于分组,
?:
所以它不会捕获匹配项。我曾经[ ]
强调该空间是有意的;这是没有必要的。我还添加
?
了使空间可选,因为history
(和r
?)可能没有空间。
推荐阅读
- javascript - 如何计算 HTMLAudio 播放了多少次?
- javascript - 如何将 Bulma 页面加载器扩展添加为 Vue 组件?
- vue.js - 编辑 v-for 中的项目
- c# - Identityserver4 登录 ValidateAntiForgeryToken
- css - 为什么我看不到这个内联 div 的背景颜色?
- javascript - 使用下拉列表 PHP/MySQL/HTML 从数据库中检索数据
- azure - 能否从 Azure 中部署的 Corda 节点访问 Azure SQL 数据库中的数据?
- java - Axios 请求 - 来自 PHP API 的 Gzip 数据
- .net-core - 如何修复 dbcontext 脚手架“用户 {'username} 登录失败”
- yii - 表单未在 Yii 2 中提交