uniq -c之后的处理需要注意。首先是如何搜索那个计数,匹配若干个空格开头然后2之后紧接空格的。
然后截取的时候需要先处理好前面的一大堆空格,不然直接cut -d “ “会出很多空格

1
2
3
4
5
6
7
8
9
#!/bin/dash

sort -t "|" -k 2,2 | # 按照学号进行排序
cut -d "|" -f 2,3 | # 然后把学号和名字截出来
uniq -c | # 统计每个学号出现的次数
grep "^[[:space:]]*2 " | # 截取计数次数为2的行
cut -d '|' -f 1 | # 开始试图截取学号
tr -s ' ' | # 把uniq-c前面产生的空格压缩成一个
cut -d ' ' -f 3 # 最后把学号截出来

用set去重。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/env python3

import sys

guys = set()
for line in sys.stdin:
line = line.strip()
if not line:
continue
field = line.split("|")
id_and_name = field[1:3]
guys.add(tuple(id_and_name))

# 循环结束后set里面就是一大堆人的id和名字的元组

# 接下来提取名字并截取后面的部分放到列表中,排序后再输出
ans = []
for id_name in guys:
name = id_name[1]
last_name = name.split(", ")[-1]
last_name = last_name.split(" ")[0]
ans.append(last_name)

ans.sort()
for last_name in ans:
print(last_name)

要用学号和名字一起来去重。

cut和python的split方法不一样的地方在于cut -d选项只能放一个字符,所以用逗号分割之后,后半段的名字会以空格开头,因此最后用空格分割去找第一个名字的时候需要用第二个。

1
2
3
#!/bin/dash

cut -d "|" -f 2,3 | sort -u | cut -d "," -f 2 | sort | cut -d " " -f 2

需要注意空格。注意strip

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env python3

import sys

for line in sys.stdin:
field = line.strip().split('|')
# 需要提前找好空格的长度
raw_name_len = len(field[2].rstrip())
space_len = len(field[2]) - raw_name_len

name = field[2].strip().split(', ')
name = name[::-1]
newname = " ".join(name)
field[2] = newname + " " * space_len
print("|".join(field))

gzip的命令 mkdir的-p选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/dash

if [ -f "log.6" ];then
mkdir -p archive

today=$(date +'%Y_%m_%d')

gzip -c log.6 > "archive/log.${today}.gz"

rm -f log.6
fi

if [ -f "log.5" ];then mv log.5 log.6; fi
if [ -f "log.4" ];then mv log.4 log.5; fi
if [ -f "log.3" ];then mv log.3 log.4; fi
if [ -f "log.2" ];then mv log.2 log.3; fi
if [ -f "log.1" ];then mv log.1 log.2; fi
if [ -f "log" ];then mv log log1; fi

如果只让用之前学过的方法的话,就只能手动这样提取前后缀然后拼接了。对于$2的数字的匹配是贪婪的,会匹配到最后一位数字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/dash

# 提取前缀和后缀 以及中间的数字 叠加并拼接

prefix=$(echo "$1" | sed 's/[0-9].*//')
suffix=$(echo "$1" | sed 's/.*[0-9]//')

# 提取数字
n=$(echo "$1" | tr -dc '0-9')
m=$(echo "$2" | tr -dc '0-9')

i="$n"

while [ "$i" -le "$m" ]; do
echo "${prefix}${i}${suffix}"
i=$((i + 1))
done

还有一种方法是shell参数扩展,

Read more »

写完才知道ls 文件名 | wc -l是不多一行可以直接出结果的 ,我用的是-l会多一行total。
我以为不加选项的ls是没法用wc的,因为似乎不是每行一个输出。

值得注意的是这个*,它会匹配当前目录下的所有文件和目录,包括隐藏文件和目录。
这里的*是通配符,触发了shell的路径名展开机制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/dash

# 当前目录下的目录 其内有多少个是具有两个以上文件或目录的

for item in *; do
if [ -d "$item" ]; then
count=$(ls -l "$item" | wc -l)
count=$((count - 1))

if [ "$count" -ge 2 ]; then
echo "$item"
fi
fi
done

q1的python-stdin实现

用startswith来匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env python3

import sys

count = 0

for line in sys.stdin:
field = line.strip().split("|")

if len(field) >=2 and field[-2].startswith("3711/"):
count += 1

print(count)

0难度

1
2
3
#!/bin/dash

grep "|3711/" | wc -l

先检查是否已经存在拓展名,即文件名中是否包含”.”

然后检查开头是不是#!

再检查这个第一行是否包含有效的解释器,但应该是不需要检验可用性的,只需要看是否有那个字样

Read more »
0%