考虑以下命令:
$ awk 'BEGIN { system("ed") }'
q
$ echo hello | awk 'BEGIN { system("ed") }'
?
$
在第一种情况下,我可以运行 ed,然后留在编辑器中,并使用 q 命令手动退出;但在第二种情况下,ed 自动退出。为什么 ed 交互式会话在第二个命令中不起作用?有没有办法在管道中运行 AWK 系统函数来调用交互式命令?
考虑以下命令:
$ awk 'BEGIN { system("ed") }'
q
$ echo hello | awk 'BEGIN { system("ed") }'
?
$
在第一种情况下,我可以运行 ed,然后留在编辑器中,并使用 q 命令手动退出;但在第二种情况下,ed 自动退出。为什么 ed 交互式会话在第二个命令中不起作用?有没有办法在管道中运行 AWK 系统函数来调用交互式命令?
在我的 macOS 和 Linux 系统上,我使用 运行 ed alias ed='rlwrap ed'
。在 macOS 上使用 rlwrap 0.46.1 (2022),我可以自由创建带有标签的文件,例如:
$ ed
a
foo<TAB>bar
但是在我的 Linux 系统上安装了 rlwrap 0.43 (2016) 我无法使用标签,除非我像这样退出:
$ ed
a
foo<ESCAPE><TAB>bar
我知道我应该着手升级我的 Linux 服务器;但根据 apt 的说法,rlwrap 目前是最晚的。是否有一些 rlwrap 选项可以让我恢复我的标签?我尝试在 rlwrap 手册页中搜索“tab”;但没有找到任何东西。
给定以下文件:
foo bar baz
this and that
然后我可以用 ed(1) 轻松通过全局替换“展开”这些行:
g/ /s//\
/g
其结果为:
foo
bar
baz
this
and
that
但是,有什么方法可以平滑地“折线”呢?
我不能在习语中使用\n
或模式。目前我使用以下方法:\<newline>
g/re/s
1
+,++s/^/ /
--,.jp
++,+++s/^/ /
--,.jp
,p
找回:
foo bar baz
this and that
但它非常笨重,我想知道是否有更好的方法!
考虑一下我的简陋hello.html
文件,它是用强大的编辑器编辑的:
$ ed hello.html
28
,p
<title>Hello world!</title>
在标题HTML 标签内进行编辑的一般方法是什么(如果您可以在任何 HTML 标签内进行编辑,那就更好了)?
我尝试了在标签内匹配的正则表达式:
s/>.*/>My new title/p
<title>My new title
u
.
<title>Hello world!</title>
</title>
但是,可悲的是,您可以看到我砍掉了我的标签(每次都输入该位的工作量太大了!)。
为了进一步学习,我浏览了 Pascal 中的软件工具页面到 174 — 请参阅https://archive.org/details/softwaretoolsinp00kern/page/174/mode/1up?view=theater页面 — 并发现了&
有助于到达句子中间:
s/world/& again/p
<title>Hello world again!</title>
但是,这不太正确,因为我想替换中间,而不仅仅是到达中间。
我完全困惑为什么当有两个范围时我不能用 ed 打印这个范围- 请参阅file2.tf文件 - ;但当只有一个范围时我可以打印- 请参阅file1.tf文件 - 并且我可以使用 gsed (macOS 上的 GNU sed)命令进行打印;但我无法用 ed 打印。请考虑我的 shell 会话并澄清我的误解:
$ ed -s file1.tf <<<',n'
1 # some comment
2 module "hello_world" {
3 source = "./mydir"
4 }
5 # another comment
$ ed -s file1.tf <<<'/module.*world/,/}/p'
module "hello_world" {
source = "./mydir"
}
$ ed -s file2.tf <<<',n'
1 # some comment
2 module "hello_world" {
3 source = "./mydir"
4 }
5 # another comment
6 # some comment
7 module "hello_again" {
8 source = "./anotherdir"
9 }
10 # another comment
$ ed -s file2.tf <<<'/module.*again/,/}/p'
?
$ gsed -n '/module.*again/,/}/p' file2.tf
module "hello_again" {
source = "./anotherdir"
}
更新:相反方向有效;但我不知道为什么:
$ ed -s file2.tf <<<'?module.*again?,?}?p'
module "hello_again" {
source = "./anotherdir"
}
更新 2:该??
方法实际上并没有按预期工作(如果有像file3.tf文件示例中那样的三个部分),请参阅答案以获取解释。
$ ed -s file3.tf <<<,n
1 # some comment
2 module "hello_world" {
3 source = "./mydir"
4 }
5 # another comment
6 # some comment
7 module "hello_again" {
8 source = "./anotherdir"
9 }
10 # another comment
11 # some comment
12 module "hello_yet_again" {
13 source = "./yetanotherdir"
14 }
15 # another comment
$ ed -s file3.tf <<<'?module.*hello_again?,?}?p'
module "hello_again" {
source = "./anotherdir"
}
# another comment
# some comment
module "hello_yet_again" {
source = "./yetanotherdir"
}
我不确定我的系统是否发生了某些变化,但我发现通过我的grep
命令过滤 Unix 手册页不起作用。你知道怎么了吗?
例如,考虑从以下代码编译的jq 手册页。
.
.IP "\(bu" 4
\fB\-\-slurp\fR/\fB\-s\fR:
.
.IP
Instead of running the filter for each JSON object in the input, read the entire input stream into a large array and run the filter just once\.
.
如果我想快速查找开关,那么我通常会通过以下终端会话显示--slurp
来过滤jq
手册页。grep
$ man jq | grep -- --slurp
$
注意什么都没有返回。这很奇怪,预期的结果类似于以下内容。
$ man jq | grep -- --slurp
• --slurp/-s:
这是意料之中的,因为如果我实际运行man jq
命令并使用/
搜索键,然后搜索--slurp
,那么就可以了。
# ...
• --slurp/-s:
Instead of running the filter for each JSON object in the input, read the entire input stream into a large array and run the filter just once.
我猜特殊字符有问题,但我不确定。我尝试通过命令放置手册页,cat
但这也没有用。我还尝试删除所有特殊字符——请参阅如何删除 Linux 文本中的所有特殊字符——但这也没有用。
$ man jq | cat | grep -- --slurp
$
$ man jq | sed $'s/[^[:print:]\t]//g' | grep -- --slurp
$
如果这是相关的,请查看有关我的系统的以下详细信息。
$ neofetch --off
OS: macOS 13.0.1 22A400 x86_64
Host: MacBookPro16,1
Kernel: 22.1.0
Uptime: 6 days, 1 hour, 3 mins
Packages: 145 (brew)
Shell: bash 3.2.57
Resolution: 1792x1120@2x
DE: Aqua
WM: Quartz Compositor
WM Theme: Blue (Light)
Terminal: iTerm2
Terminal Font: Monaco 12
CPU: Intel i7-9750H (12) @ 2.60GHz
GPU: Intel UHD Graphics 630, AMD Radeon Pro 5300M
Memory: 10425MiB / 16384MiB
假设 podman 安装在 linux 系统和名为 baz.service 的 systemd 单元上:
# /etc/systemd/system/baz.service
[Service]
ExecStart=/usr/bin/podman run --rm --tty --name baz alpine sh -c 'while true; do date; sleep 1; done'
ExecStop=/usr/bin/podman stop baz
然后 baz.service 开始了:
# systemctl daemon-reload
# systemctl start baz.service
然后,当我检查单元的状态时,我在 /system.slice/baz.service cgroup 中看不到sh
orsleep
进程
# systemctl status baz
● baz.service
Loaded: loaded (/etc/systemd/system/baz.service; static; vendor preset: enabl
Active: active (running) since Sat 2019-08-10 05:50:18 UTC; 14s ago
Main PID: 16910 (podman)
Tasks: 9
Memory: 7.3M
CPU: 68ms
CGroup: /system.slice/baz.service
└─16910 /usr/bin/podman run --rm --tty --name baz alpine sh -c while
# ...
我期待在我的 baz.service 状态中看到sh
and sleep
children,因为我听说 redhat 的人说 podman 使用传统的 fork-exec 模型。
如果 podman 进行了 fork 和 exec,那么我的sh
和sleep
进程不会是 podman 的子进程并且与原始 podman 进程在同一个 cgroup 中吗?
我期待能够使用 systemd 和 podman 来管理我的容器,而无需让孩子转到另一个父母并逃离我的 baz.service ssystemd 单元。
查看 I 的输出ps
可以看到,sh
实际上sleep
是不同进程的子进程,称为conmon
. 我不确定 conmon 来自哪里,或者它是如何启动的,但 systemd 没有捕获它。
# ps -Heo user,pid,ppid,comm
# ...
root 17254 1 podman
root 17331 1 conmon
root 17345 17331 sh
root 17380 17345 sleep
从输出中可以清楚地看出我的 baz.service 单元没有管理 conmon -> sh -> sleep 链。
也许它们都是容器运行时,而dockerd
守护进程是人们想要摆脱的。
所以也许 docker 是这样的:
podman 就像:
所以也许 podman 使用了传统的 fork exec 模型,但它不是分叉和执行的 podman cli,而是 conmon 进程。
我感到困惑。
我在 ubuntu 服务器上,想检查内部目录的磁盘使用情况摘要,/var/lib/docker
我很困惑为什么我无法/var/lib/docker
使用 glob检查内部所有目录的磁盘使用情况*
。
该目录/var/lib/docker
显然存在并且里面有目录:
$ sudo du -s /var/lib/* | grep docker
865644 /var/lib/docker
8 /var/lib/docker-engine
$ sudo du -s /var/lib/docker/*
du: cannot access '/var/lib/docker/*': No such file or directory
$ sudo file /var/lib/docker
/var/lib/docker: directory
$ sudo ls /var/lib/docker | head -n 1
builder
$ sudo du -s /var/lib/docker/builder
20 /var/lib/docker/builder
为什么我会收到错误消息du
?
du: cannot access '/var/lib/docker/*': No such file or directory
我的错误似乎与非 root 用户有关,因为如果我切换到 root 用户,那么我可以发出du
命令:
# du -s /var/lib/docker/* | sort -n
4 /var/lib/docker/runtimes
4 /var/lib/docker/swarm
4 /var/lib/docker/tmp
4 /var/lib/docker/trust
20 /var/lib/docker/builder
20 /var/lib/docker/plugins
36 /var/lib/docker/volumes
60 /var/lib/docker/network
72 /var/lib/docker/buildkit
208 /var/lib/docker/containers
1880 /var/lib/docker/image
863328 /var/lib/docker/overlay2
当我开始systemd-cgtop
按?
键时,我想阅读帮助菜单,但几秒钟后它消失了。如何防止帮助菜单消失?
如果我输入man tmux
,那么/join-pane
我会直接转到我正在寻找的子命令:
但是,如果我 grep 手册页,那么我什么也得不到:
$ man tmux | grep join-pane
$ echo $?
1
如果我尝试不同的东西,那么它确实有效:
$ man tmux | grep 'terminal multiplexer'
tmux -- terminal multiplexer
tmux is a terminal multiplexer: it enables a number of terminals to be
关于我的操作系统和我正在使用的命令的一些详细信息:
$ uname -a
Darwin home.local 17.7.0 Darwin Kernel Version 17.7.0: Thu Jun 21 22:53:14 PDT 2018; root:xnu-4570.71.2~1/RELEASE_X86_64 x86_64
$ grep --version
grep (BSD grep) 2.5.1-FreeBSD
$ man --version
man, version 1.6c
$ tmux -V
tmux 2.7
根据关于这是一个终端问题的评论,我尝试了一些无效的模式:
$ man tmux | grep join\-pane
$ man tmux | grep "join-pane"
$ man tmux | grep 'join-pane'
$ man tmux | grep 'join\-pane'
$ man tmux | grep "join\-pane"
$ man tmux | grep -e join-pane
我很好奇如何将 heredocs 作为文件传递给命令行实用程序的理论。
最近,我发现我可以将文件作为 heredoc 传递。
例如:
awk '{ split($0, arr, " "); print arr[2] }' <<EOF
foo bar baz
EOF
bar
这对我有利有几个原因:
例如:
ruby <<EOF
puts "'hello $HOME'"
EOF
'hello /Users/mbigras'
ruby <<'EOF'
puts "'hello $HOME'"
EOF
'hello $HOME'
我不清楚发生了什么。似乎shell认为heredoc是一个内容等于heredoc值的文件。我已经将这种技术与 cat 一起使用,但我仍然不确定发生了什么:
cat <<EOL
hello world
EOL
hello world
我知道cat
打印文件的内容,所以大概这个heredoc是某种临时文件。
当我“将heredoc传递给命令行程序”时,我对到底发生了什么感到困惑。
这是一个使用ansible-playbook的示例。我将实用程序作为heredoc 传递给一个剧本;但是它失败了,如使用所示echo $?
:
ansible-playbook -i localhost, -c local <<EOF &>/dev/null
---
- hosts: all
gather_facts: false
tasks:
- name: Print something
debug:
msg: hello world
EOF
echo $?
5
但是,如果我将实用程序传递给相同的heredoc,但在它/dev/stdin
之前成功
ansible-playbook -i localhost, -c local /dev/stdin <<EOF &>/dev/null
---
- hosts: all
gather_facts: false
tasks:
- name: Print something
debug:
msg: hello world
EOF
echo $?
0
ansible-playbook
失败但第二个版本成功?/dev/stdin
在heredoc之前通过有什么意义?ruby
或awk
不需要/dev/stdin
heredoc之前的?