送你一道shell题
学习夜老师博客https://7r1umphk.github.io/post/qun-zhu-ti.html (opens new window),看到一道群主不知道什么时候发的题目,来学习一下

因为对shell的掌握非常浅显,详细理解下题目
# 题目解读
题目源码如下
PATH=/usr/bin
read INPUT < <(head -n1 | tr -d "[A-Za-z0-9/]")
eval "$INPUT"
1
2
3
2
3

解释:
- 重置环境变量
- 读取输入,读取第一行并删除掉字母数字和斜杠,储存在INPUT变量中
- eval执行INPUT变量值
详细讲讲第二条命令
read INPUT < <(head -n1 | tr -d "[A-Za-z0-9/]")
1
分成三部分:
read INPUT 、<、 <(head -n1 | tr -d "[A-Za-z0-9/]")
优先级问题,shell会先解释执行第三部分的进程替换语法,执行括号内的命令,把整体结果存放在临时文件中
# head
┌──(npc㉿kali)-[~]
└─$ head --help
用法:head [选项]... [文件]...
将每个 <文件> 的前 10 行输出到标准输出。
如果没有指定 <文件>,或者 <文件> 为 "-",则从标准输入读取。
-c, --bytes=[-]数字 显示每个文件的前 <数字> 字节内容;
-n, --lines=[-]数字 显示每个文件的前 <数字> 行内容而非前 10 行内容;
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
head命令默认读取文件前10行,如果没有指定文件或文件为-,则从标准输入读取,即从键盘输入
所以这里head -n1 读取键盘输入第一行
# tr
┌──(npc㉿kali)-[~]
└─$ tr --help
用法:tr [选项]... 字符串1 [字符串2]
从标准输入中替换、缩减和/或删除字符,并将结果写到标准输出。
<字符串1> 和 <字符串2> 用于指定字符数组 <数组1> 和 <数组2>,这两个
<数组> 将控制程序的行为。
-c, -C, --complement 使用 <数组1> 的补集
-d, --delete 删除 <数组1> 中的字符,不进行替换
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
tr -d "[A-Za-z0-9/]" 删除输入中所有字母、数字和斜杠
# 进程替换
<()语法会创建一个匿名管道,把括号内命令的执行结果重定向到该管道中(临时文件/dev/fd/xx)
┌──(npc㉿kali)-[~]
└─$ echo <(ls)
/proc/self/fd/11
┌──(npc㉿kali)-[~]
└─$ echo <(echo 'test')
/proc/self/fd/11
┌──(npc㉿kali)-[~]
└─$ cat <(echo 'test')
test
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11

# read
┌──(npc㉿kali)-[~]
└─$ tldr read
- 读取键盘输入的数据赋值给变量:
read 变量
1
2
3
4
5
2
3
4
5

那么read INPUT就是从键盘输入中读取内容,赋值给INPUT变量,后面存在一个重定向符号<,表示从文件中读取内容,作为前面read命令的输入来源
head/read这些从键盘输入的命令都可以接收重定向的内容
┌──(npc㉿kali)-[~/hackmyvm/test]
└─$ head -n1 < <(ls)
1.sh
┌──(npc㉿kali)-[~/hackmyvm/test]
└─$ read aaa < <(ls)
┌──(npc㉿kali)-[~/hackmyvm/test]
└─$ echo $aaa
1.sh
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 题目思路
现在知道
- 题目从键盘输入读取第一行
- 删除掉字母数字和斜杠
- 把结果赋值给INPUT变量
- 执行INPUT变量内容
# 通配符
把命令写进文件,通过. 文件名的方式执行,利用通配符匹配到执行的文件
┌──(npc㉿kali)-[~/hackmyvm/test]
└─$ cat 1.sh
PATH=/usr/bin
read INPUT < <(head -n1 | tr -d "[A-Za-z0-9/]")
eval "$INPUT"
┌──(npc㉿kali)-[~/hackmyvm/test]
└─$ which whoami
/usr/bin/whoami
┌──(npc㉿kali)-[~/hackmyvm/test]
└─$ echo 'whoami' > 1
┌──(npc㉿kali)-[~/hackmyvm/test]
└─$ chmod +x 1.sh
┌──(npc㉿kali)-[~/hackmyvm/test]
└─$ chmod +x 1
┌──(npc㉿kali)-[~/hackmyvm/test]
└─$ bash 1.sh
. ?
npc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# shell变量
在shell环境里,有一些变量会自动被赋值
这里将一个特殊的变量$@,这是一个位置参数变量,表示传递给脚本或函数的所有参数,我以前会利用这个命令绕过关键字过滤
在没有参数时,它的值为空字符串,放进命令里不影响解析
┌──(npc㉿kali)-[~/hackmyvm/test]
└─$ mkdir -p testdir
┌──(npc㉿kali)-[~/hackmyvm/test]
└─$ e$@cho '1111' > te$@stdir/1.$@txt
┌──(npc㉿kali)-[~/hackmyvm/test]
└─$ c$@at tes$@tdir/1.t$@xt
1111
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
在脚本或者函数里,可以打印传来的位置参数
┌──(npc㉿kali)-[~/hackmyvm/test]
└─$ cat get-params.sh
echo $0
echo $1
echo $2
echo $@
┌──(npc㉿kali)-[~/hackmyvm/test]
└─$ sh get-params.sh 1 2 3 4
get-params.sh
1
2
1 2 3 4
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
$0b变量表示脚本名称,$@表示所有参数
所以可以通过$@变量,构造命令

还有一个位置参数的变量$*,会把所有参数当成一个整体,空格隔开
echo $*;
1


编辑 (opens new window)
最后一次更新于: 2025/11/03, 02:17:47