Tyl*_*ore 7 regex bash shell perl function
我试图在perl cmd执行块中重用脚本中稍后在bash脚本中定义的shell函数.对匹配一个正则表达式(捕获组#2)后,对perl cmd的调用基本上需要运行定义的shell函数.请参阅下面的代码定义
bash shell脚本中的相关函数定义:
evalPS() {
PS_ARGS=$(eval 'echo -en "'${1}'"' | sed -e 's#\\\[##g' -e 's#\\\]##g')
PS_STR=$((set +x; (PS4="+.$PS_ARGS"; set -x; :) 2>&1) | cut -d':' -f1 | cut -d'.' -f2)
echo -en "${PS_STR}"
}
Run Code Online (Sandbox Code Playgroud)
上面的定义使用一些bashisms和hacks来评估用户对字符串的真实提示.
需要在下一个函数中在perl中调用该函数:
remPS() {
# store evalPS definition
EVALPS_SOURCE=$(declare -f evalPS)
# initalize prompt
eval "$PROMPT_COMMAND" &> /dev/null
# handle args
( [[ $# -eq 0 ]] && cat - || cat "${1}" ) |
# ridiculous regex
perl -pe 's/^[^\e].*//gs' |
perl -s -0777 -e '`'"$EVALPS_SOURCE"'`; while (<>) { s%(.*?\Q$ps1\E)(?{`eval $PROMPT_COMMAND`})|(.*?\Q$ps2\E)(?{$ps2=`$\(evalPS "${PS2}"\)`})|(\Q$ps3\E)|(^\Q$ps4\E+.*?\b)%%g; } continue {print;}' -- \
-ps1="$(evalPS "${PS1}")" -ps2="$(evalPS "${PS2}")" \
-ps3="${PS3}" -ps4="${PS4:0:1}" |
perl -pe 's/(.*?)\e\[[A-Z](\a)*/\1/g'
}
Run Code Online (Sandbox Code Playgroud)
对perl的调用可以移动到一个单独的脚本,但无论哪种方式,我都找不到remPS()在perl脚本中"导入"或"源"该函数的方法.我也尝试将函数从单独的文件定义中获取到perl命令中.像这样:
perl -s -0777 -e '`. /home/anon/Desktop/flyball_labs/scripts/recsesh_lib.sh`; while (<>) { s%(.*?\Q$ps1\E)(?{`eval $PROMPT_COMMAND`})|(.*?\Q$ps2\E)(?{$ps2=`$\(evalPS "${PS2}"\)`})|(\Q$ps3\E)|(^\Q$ps4\E+.*?\b)%%g; } continue {print;}'
...
Run Code Online (Sandbox Code Playgroud)
或使用source内置:
perl -s -0777 -e '`source /home/anon/Desktop/flyball_labs/scripts/recsesh_lib.sh`; while (<>) { s%(.*?\Q$ps1\E)(?{`eval $PROMPT_COMMAND`})|(.*?\Q$ps2\E)(?{$ps2=`$\(evalPS "${PS2}"\)`})|(\Q$ps3\E)|(^\Q$ps4\E+.*?\b)%%g; } continue {print;}'
...
Run Code Online (Sandbox Code Playgroud)
为清楚起见,最后的尝试是将函数声明传递给perl,如下所示:
perl -s -0777 -e '`'"$EVALPS_SOURCE"'`; while (<>) { s%(.*?\Q$ps1\E)(?{`eval $PROMPT_COMMAND`})|(.*?\Q$ps2\E)(?{$ps2=`$\(evalPS "${PS2}"\)`})|(\Q$ps3\E)|(^\Q$ps4\E+.*?\b)%%g; } continue {print;}'
...
Run Code Online (Sandbox Code Playgroud)
在上述任何情况下没有运气..似乎.cmd运行而sourcecmd没有运行,并且可能无法将函数声明传递给perl的语法,如我的测试输出所示:
采购库定义w/sourcecmd
(1)|anon@devbox /tmp|$ remPS "${TEXT_FILE}"
sh: 1: source: not found
...
Run Code Online (Sandbox Code Playgroud)
采购w/shell .cmd
(1)|anon@devbox /tmp|$ remPS "${TEXT_FILE}"
sh: 1: evalPS: not found
...
Run Code Online (Sandbox Code Playgroud)
将声明传递给perl
(1)|anon@devbox /tmp|$ remPS "${TEXT_FILE}"
sh: 3: Syntax error: ")" unexpected (expecting "}")
sh: 1: evalPS: not found
...
Run Code Online (Sandbox Code Playgroud)
问)如何在perl中"导入"并运行用户定义的shell命令?
A) 2可能的解决方案:
评估真实的bash提示值:
how-to-print-current-bash-prompt echo-expanded-ps1
注意:我之所以选择此实现,是evalPS()因为使用scriptcmd解决方法不可靠并且使用call bind_variable()bash函数需要root权限(有效地更改用户的提示).
注意:该函数必须在每次匹配后运行,$PS2以重新评估新提示并有效匹配下一次迭代(就像在真正的shell会话中一样).我对此的用例是许多人(包括我自己)设置他们$PROMPT_COMMAND迭代一个整数,指示$PS1当前行的哪个行号(或偏移),并显示在其中$PS2.
在perl中获取shell代码:
how-to-run-source-command-linux-from-a-perl-script can-we-source-a-shell-script-in-perl-script sourcing-a-shell-script-from-a-perl-脚本
或者,如果有人知道如何将我的实现evalPS()转换为perl代码,那也会有效,但我相信这是不可能的,因为评估的字符串是使用"set hack"获得的,据我所知,这是严格意义上的基础.
我们欢迎所有的建议!
有关正在解析的数据的更多信息..
文本文件如下所示(cat -A输出):
^[]0;anon@ - 3^G^[[1m^[[31m(^[[36m1^[[31m)|^[[33manon^[[32m@^[[34mdevbox ^[[35m/tmp^[[31m|^[[36m^[[37m$ ^[(B^[[mecho test^M$
test^M$
^[[1m^[[31m(^[[36m1^[[31m)|^[[33manon^[[32m@^[[34mdevbox ^[[35m/tmp^[[31m|^[[36m^[[37m$ ^[(B^[[mecho \^M$
^[[1m^[[31m[^[[36m2^[[31m]|^[[33m-^[[32m-^[[34m-^[[35m> ^[(B^[[m\^M$
^[[1m^[[31m[^[[36m3^[[31m]|^[[33m-^[[32m-^[[34m-^[[35m> ^[(B^[[m\^M$
^[[1m^[[31m[^[[36m4^[[31m]|^[[33m-^[[32m-^[[34m-^[[35m> ^[(B^[[mtest^M$
test^M$
^[[1m^[[31m(^[[36m1^[[31m)|^[[33manon^[[32m@^[[34mdevbox ^[[35m/tmp^[[31m|^[[36m^[[37m$ ^[(B^[[mexit^M$
exit^M$
Run Code Online (Sandbox Code Playgroud)
或类似(less格式化):
ESC]0;anon@ - 3^GESC[1mESC[31m(ESC[36m1ESC[31m)|ESC[33manonESC[32m@ESC[34mdevbox ESC[35m/tmpESC[31m|ESC[36mESC[37m$ ESC(BESC[mecho test
test
ESC[1mESC[31m(ESC[36m1ESC[31m)|ESC[33manonESC[32m@ESC[34mdevbox ESC[35m/tmpESC[31m|ESC[36mESC[37m$ ESC(BESC[mecho \
ESC[1mESC[31m[ESC[36m2ESC[31m]|ESC[33m-ESC[32m-ESC[34m-ESC[35m> ESC(BESC[m\
ESC[1mESC[31m[ESC[36m3ESC[31m]|ESC[33m-ESC[32m-ESC[34m-ESC[35m> ESC(BESC[m\
ESC[1mESC[31m[ESC[36m4ESC[31m]|ESC[33m-ESC[32m-ESC[34m-ESC[35m> ESC(BESC[mtest
test
ESC[1mESC[31m(ESC[36m1ESC[31m)|ESC[33manonESC[32m@ESC[34mdevbox ESC[35m/tmpESC[31m|ESC[36mESC[37m$ ESC(BESC[mexit
exit
Run Code Online (Sandbox Code Playgroud)
我$PROMPT_COMMAND和相应的提示($PS1- $PS4)例如:
PROMPT_COMMAND='TERM_LINE_NO=1'
PS1="\[$(tput bold)\]\[$(tput setaf 1)\](\[$(tput setaf 6)\]\${TERM_LINE_NO}\[$(tput setaf 1)\])|\[$(tput setaf 3)\]\u\[$(tput setaf 2)\]@\[$(tput setaf 4)\]\h \[$(tput setaf 5)\]\w\[$(tput setaf 1)\]|\[$(tput setaf 6)\]\$(parse_git_branch)\[$(tput setaf 7)\]\\$ \[$(tput sgr0)\]"
PS2="\[$(tput bold)\]\[$(tput setaf 1)\][\[$(tput setaf 6)\]\$((++TERM_LINE_NO))\[$(tput setaf 1)\]]|\[$(tput setaf 3)\]-\[$(tput setaf 2)\]-\[$(tput setaf 4)\]-\[$(tput setaf 5)\]> \[$(tput sgr0)\]"
PS3=""
PS4="+ "
Run Code Online (Sandbox Code Playgroud)
答案是放弃整个想法并使用更好的想法。
让我们先退后一步.. 总体情况:
目标是使script程序输出整个录制会话的可执行 shell 脚本。
回到答案..
上面的实现应该从输出中删除所有提示和控制字符script(这是我给出的输入示例),然后删除每个命令的输出(即任何不包含控制字符的行) 。
事实证明,将evalPS函数传递给perl执行是相当多余的,并且正确获取bash和perl扩展参数是一场噩梦。
最终解决方案
废弃了 perl 正则表达式的想法,并使用子 shell 和历史重定向的组合来获取整个script会话运行时的命令。
整个实现如下所示:
# log cmds to script file as they are entered (unbuffered)
# spawn script cmd in subshell and wait for it to finish
wait -n
(
history -c
export HISTFILE="${SCRIPT_FILE}"
shopt -s histappend
script -q --timing="${TIME_FILE}" "${REC_FILE}"
history -a
)
...
Run Code Online (Sandbox Code Playgroud)
简单易读!:)希望这对将来
尝试制作自己的模组的人有所帮助,干杯!script
| 归档时间: |
|
| 查看次数: |
337 次 |
| 最近记录: |