经常写 shell 脚本的同学一定用过一个名为 basename 的程序。这个程序可以把一个路径里最后一部分提取出来,像下面这样:


033-basename 程序_字符串操作


图1 basename 运行结果


接下来你懂的,用 go 来实现这个 basename 程序。

本文的程序路径是:​​gopl/basictypes/basename​

1. 版本一

package main

import (
"fmt"
"os"
)

func main() {
if len(os.Args) <= 1 {
usage()
os.Exit(-1)
}

s := basename(os.Args[1])
fmt.Println(s)
}

func basename(s string) string {
// 处理只有一个 "/" 的情况
if len(s) == 1 && s[0] == '/' {
return s
}

// 最后一个字符是 '/' 则跳过
if len(s) > 0 && s[len(s)-1] == '/' {
s = s[:len(s)-1]
}

for i := len(s) - 1; i >= 0; i-- {
if s[i] == '/' {
s = s[i+1:]
break
}
}

return s
}

func usage() {
fmt.Println("go run basename01.go <path>")
}

2. 版本二

go 语言提供了很多有用的包,strings 包就是其中之一,这是一个字符串处理专用的包,常见的关于字符串操作,比如 ​​trim, split, join​​​ 等全都有。下面是使用 strings 包的 ​​LastIndexByte​​​ 方法查询最后一个 ​​'/'​​.

package main

import (
"fmt"
"os"
"strings"
)

func main() {
if len(os.Args) <= 1 {
usage()
os.Exit(-1)
}

s := basename(os.Args[1])
fmt.Println(s)
}

func basename(s string) string {
// 处理只有一个 "/" 的情况
if len(s) == 1 && s[0] == '/' {
return s
}

// 最后一个字符是 '/' 则跳过
if len(s) > 0 && s[len(s)-1] == '/' {
s = s[:len(s)-1]
}

i := strings.LastIndexByte(s, '/')
s = s[i+1:]
return s
}

func usage() {
fmt.Println("go run basename02.go <path>")
}

3. 总结

  • 熟悉 strings 包
  • Tips:

关于 string 切片有一点细节需要注意。如果一个 ​​string s​​​ 长度是 5,我们取 ​​s[5]​​​ 是非法的,因为越界了,但是执行切片 ​​s[5:]​​ 是正确的,它会返回一个空串。