linux 如何使用sed、awk或perl替换/etc/skel/.bashrc或.bashrc文件中的PS1变量?

dzhpxtsq  于 2023-06-21  发布在  Linux
关注(0)|答案(1)|浏览(107)
    • 编辑-06/08/23-原始问题基本相同**

感谢Charles Duffy在评论中提供宝贵的反馈。原来的问题出现在第1项的上下文中。但根据反馈,项目2似乎是管理系统管理任务的更好选择。当我完成对perl/etc/profile.d的研究后,我可能会在这里打开另一个问题,或者在我的答案中发布一些信息。
1.原始问题:如何使用sedawkperl搜索和替换文件中的文字字符串,例如.bashrc文件中的PS1=<string>
1.更好的问题是如何使用存储在/etc/profile.d中的脚本启用所需的提示行为,这些脚本在用户登录时自动执行?
目标是在Debian PC和DietPi(ARM)Linux系统上自动化自定义bash提示符。自定义提示符插入一个空行,将命令与终端输出分开,看起来像这样,但颜色不同:

root@dpiBox /root
#

user@dpiBox /home/user
$

其中root@dpiBox是红色; user@dpiBox为绿色;并且当前工作目录总是以蓝色显示。
当创建新的user时,/etc/skel/.bashrc的副本将作为/home/user/.bashrc放置在用户的主目录中。root用户已将副本创建为/root/.bashrc
我最初的计划是在添加新用户之前通过脚本编辑/etc/skel/.bashrc,并手动编辑/root/.bashrc。但是当root或任何用户登录时,它会自动执行正确安装在/etc/profile.d下的脚本。Charles Duffy似乎建议使用此功能来更好地管理系统管理挑战!
默认/etc/skel/.bashrc/root/.bashrc/home/user/.bashrc中的相关行

# /root/bashtest (simulates default .bashrc)
# /etc/skel/.bashrc
# /root/.bashrc
# /home/user/.bashrc

#force_color_prompt=yes

if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi

第1步-取消注解行以打开颜色提示:

force_color_prompt=yes

第2步-用新的PS1(如图所示)替换旧的PS1(如图所示)以自定义bash提示符:

PS1='${debian_chroot:+($debian_chroot)}\n\[\033[01;32m\]\u@\h\[\033[00m\]\[\033[01;34m\] $(pwd -P) \[\033[00m\]\n\$ '

/home/user/.bashrc的代码[01;32m\]为绿色。将此代码更改为[01;31m\],对于/root/.bashrc为红色。

    • 步骤1-sed:**良好结果

/usr/local/bin/bashsed(编辑bashtest/. bashrc的开发脚本)

#!/bin/bash
# uncomment to force color prompt on
off="#force_color_prompt=yes"
on="force_color_prompt=yes"
sed -i "s|$off|$on|" /root/bashtest

sed代码与用于定义onoff的双引号或单引号一起使用。必须在sed命令中使用双引号。

    • 步骤1-perl:**结果良好

/usr/local/bin/bashperl(编辑bashtest/. bashrc的开发脚本)

#!/bin/bash
# uncomment to force color prompt on
perl -i.bak -pe 's/#force_color_prompt=yes/force_color_prompt=yes/' /root/bashtest

i.bak交换机将/root/bashtest备份为/root/bashtest.bak,然后就地编辑文件。此命令可以在命令行上使用,而无需使用i.bak开关。

    • 步骤2-sed:**sed -i "s|$old|$new|" /root/bashtest的错误结果

/usr/local/bin/bashsed(编辑bashtest/. bashrc的开发脚本)

#!/bin/bash
# replace old PS1 with new PS1
# old                                    \[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\
# PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '

old='\\[\\033\[01;32m\\]\\u@\\h\\[\\033[00m\\]:\\[\\033\[01;34m\\]\\w\\[\\033\[00m\\]\\'

# new                                    \n\[\033[01;32m\]\u@\h\[\033[00m\]\[\033[01;34m\] $(pwd -P) \[\033[00m\]\n\
# PS1='${debian_chroot:+($debian_chroot)}\n\[\033[01;32m\]\u@\h\[\033[00m\]\[\033[01;34m\] $(pwd -P) \[\033[00m\]\n\$ '

new='\\n\\[\\033\[01;32m\\]\\u@\\h\\[\\033\[00m\\]\\[\\033\[01;34m\\] \$(pwd -P) \\[\\033\[00m\\]\\n\\'

sed -i "s|$old|$new|" /root/bashtest

第2步:当使用双引号定义oldnew时,代码运行没有错误,但产生无结果。当使用单引号定义oldnew时,代码抛出错误sed: -e expression #1, char 149: unterminateds' command`。

    • 编辑-06/08/23-评论**

bash脚本中使用perl调用将我的解决方案发布到步骤2
根据Charles Duffy的反馈,Step 2perl解决方案可以修改为使用存储为bash环境变量的文字字符串。相关信息在此链接下的页面顶部附近提供:
https://mywiki.wooledge.org/BashFAQ/021
根据CharlesDuffy的说法,当用户登录时,脚本应该从/etc/profile.d运行,以便更好地管理系统管理员任务。我需要做更多的研究来理解这种反馈。这里有两个链接可能会有帮助:
https://serverfault.com/questions/434321/when-are-scripts-inside-etc-profile-d-executed
https://unix.stackexchange.com/questions/64258/what-do-the-scripts-in-etc-profile-d-do

    • 原题链接**

我已经广泛搜索,在下面的上下文中尝试了几十个实验,我无法理解这些参考文献:
https://linuxhint.com/replace_string_in_file_bash/
Why would sed have trouble seeing my PS1 prompt?
Replacement of PS1 variable in .bashrc using Sed or Perl
Regarding sed expression evaluation in shell
所以我需要检查我的"sed"!如果awk可以完成这项工作,我不介意使用它,但是在插入文字字符串之前,我需要查看简单的命令结构。否则,我总是搞砸语法。

n53p2ov0

n53p2ov01#

使用perl而不是sedawk求解。主要依赖于以下参考:
https://www.perl.com/pub/2004/08/09/commandline.html/
PS1中的old文字字符串:

\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\

perl匹配的old字符串转义:

\\\[\\033\[01;32m\\]\\u@\\h\\\[\\033\[00m\\]:\\\[\\033\[01;34m\\]\\w\\\[\\033\[00m\\]\\

PS1中的new文字字符串

\n\[\033[01;32m\]\u@\h\[\033[00m\]\[\033[01;34m\] $(pwd -P) \[\033[00m\]\n\

perl替换操作的new字符串转义:

\\n\\[\\033\[01;32m\\]\\u@\\h\\\[\\033\[00m\\]\\\[\\033\[01;34m\\] \$\(pwd -P\) \\[\\033\[00m\\]\\n\\

在命令行上使用pattern调试文字字符串的转义序列:

perl 's/old/DummyString/' < ps1old > ps1out; cat ps1out
# ~/ps1old

#force_color_prompt=yes

if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
perl 's/new/DummyString/' < ps1new > ps1out; cat ps1out
# ~/ps1new

#force_color_prompt=yes

if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\n\[\033[01;32m\]\u@\h\[\033[00m\]\[\033[01;34m\] $(pwd -P) \[\033[00m\]\n\$ '
else
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
perl 's/old/new/' < ps1old > ps1out; cat ps1out

带有测试输入文件ps1old的命令行解决方案将结果写入ps1out

perl -pe 's/\\\[\\033\[01;32m\\]\\u@\\h\\\[\\033\[00m\\]:\\\[\\033\[01;34m\\]\\w\\\[\\033\[00m\\]\\/\\n\\[\\033\[01;32m\\]\\u@\\h\\\[\\033\[00m\\]\\\[\\033\[01;34m\\] \$\(pwd -P\) \\[\\033\[00m\\]\\n\\/' < ps1old > ps1old; cat ps1out

此方法将结果写入文件ps1out,同时对占位符old和占位符new表示的文字字符串从左到右测试转义序列模式。
当转义序列失败时,文件ps1old或文件ps1new不变;文件ps1out恢复为相应输入文件的副本;而perl提供了有价值的调试信息。
当转义序列成功时,文件ps1out显示虚拟字符串DummyString,作为从左到右工作的oldnew的部分的替换,以调试转义模式。这可以一次执行一个转义字符,以系统地隔离语法错误。
调试完占位符oldnew的文字字符串后,使用perl调用将工作结果传输到bash脚本,如下所示。
一种改进可能是将更改写入新文件,然后将其移动到目标.bashrc,并保留.bashrc.bak用于备份。

如果此脚本运行不止一次,它会用编辑过的版本覆盖备份副本!

Bash脚本调用perl

#!/bin/bash

# Command line test writes result to ps1out without changing ps1old
# perl -pe 's/#force_color_prompt=yes/force_color_prompt=yes/' < ps1old > ps1out; cat ps1out

# Command line test writes result to ps1out without changing ps1old
# perl -pe 's/\\\[\\033\[01;32m\\]\\u@\\h\\\[\\033\[00m\\]:\\\[\\033\[01;34m\\]\\w\\\[\\033\[00m\\]\\/\\n\\[\\033\[01;32m\\]\\u@\\h\\\[\\033\[00m\\]\\\[\\033\[01;34m\\] \$\(pwd -P\) \\[\\033\[00m\\]\\n\\/' < ps1old > ps1old; cat ps1out

# If script is run two or more times it overwrites previous .bashrc.bak!
# Backup target .bashrc using -i.bak switch to uncomment file in place!
perl -i.bak -pe 's/#force_color_prompt=yes/force_color_prompt=yes/' .bashrc

# Replace old PS1 with new PS1 after testing PS1 escape pattern on command line
perl -i -pe 's/\\\[\\033\[01;32m\\]\\u@\\h\\\[\\033\[00m\\]:\\\[\\033\[01;34m\\]\\w\\\[\\033\[00m\\]\\/\\n\\[\\033\[01;32m\\]\\u@\\h\\\[\\033\[00m\\]\\\[\\033\[01;34m\\] \$\(pwd -P\) \\[\\033\[00m\\]\\n\\/' .bashrc

相关问题