从awk程序中的路径中提取文件名

Aas*_*shu 22 awk filenames

我有一个 awk 脚本,并且我已经向它传递了一个 CSV 文件。

awk -f script.awk /home/abc/imp/asgd.csv
Run Code Online (Sandbox Code Playgroud)

我在做什么是在script.awk. FILENAME 给了我完整的路径。由于我在 awk 中,因此无法使用basename FILENAME.

print FILENAME;
/home/abc/imp/asgd.csv
Run Code Online (Sandbox Code Playgroud)

我已经尝试过这个 script.awk

echo $FILENAME | awk -F"/" '{print $NF}'
Run Code Online (Sandbox Code Playgroud)

但我无法在script.awk. 如何进入asgd.csvawk 程序?

Sté*_*las 35

几个选项:

awk '
  function basename(file) {
    sub(".*/", "", file)
    return file
  }
  {print FILENAME, basename(FILENAME)}' /path/to/file
Run Code Online (Sandbox Code Playgroud)

或者:

awk '
  function basename(file, a, n) {
    n = split(file, a, "/")
    return a[n]
  }
  {print FILENAME, basename(FILENAME)}' /path/to/file
Run Code Online (Sandbox Code Playgroud)

请注意,这些实现basename应为共同的情况下工作,但不是在角落情况下,像basename /path/to/x///他们返回空字符串,而不是x或/他们返回空字符串代替/,尽管对于普通文件,这是不应该的。

如果文件路径(直到最后一个/)包含在当前语言环境中不构成有效字符的字节序列(通常这种事情发生在 UTF-8 语言环境中,文件名编码为 8位单字节字符集)。您可以通过将语言环境固定为 C 来解决这个问题,其中每个字节序列都形成有效字符。

  • 如果您需要在现有 awk 脚本中轻松运行而不引入函数的代码,您应该使用:`n = split(FILENAME, a, "/"); 基名=a[n];`。不要使用 `sub`,因为它实际上会改变 `FILENAME` 变量(这不是函数的问题,因为 awk 使用按值调用)。 (6认同)

Avi*_*Raj 10

试试这个 awk one-liner,

$ awk 'END{ var=FILENAME; split (var,a,/\//); print a[5]}' /home/abc/imp/asgd.csv
asgd.csv
Run Code Online (Sandbox Code Playgroud)

  • 或`awk 'END{ var=FILENAME; n=split (var,a,/\//); 打印一个[n]}' /home/abc/imp/asgd.csv` (4认同)

Ser*_*nyy 9

在有命令的系统上basename,可以使用awk的system()函数或expression | getline var结构来调用外部basename命令。这可以帮助解决Stephane 的回答中提到的极端情况。

$ awk '{cmd=sprintf("basename %s",FILENAME);cmd | getline out; print FILENAME,out; exit}' /etc///passwd
/etc///passwd passwd
Run Code Online (Sandbox Code Playgroud)