AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 490524
Accepted
don_crissti
don_crissti
Asked: 2018-12-23 12:44:21 +0800 CST2018-12-23 12:44:21 +0800 CST 2018-12-23 12:44:21 +0800 CST

如果文件名包含 =,为什么 awk 会停止并等待,以及如何解决这个问题?

  • 772
awk 'processing_script_here' my=file.txt

似乎停止并无限期地等待......
这里发生了什么,我该如何让它工作?

awk filenames
  • 3 3 个回答
  • 1999 Views

3 个回答

  • Voted
  1. Chris Down
    2018-12-23T12:53:36+08:002018-12-23T12:53:36+08:00

    在大多数版本的 awk 中,要执行的程序之后的参数是:

    1. 一份文件
    2. 表格的赋值x=y

    由于您的文件名被解释为 case #2,awk 仍在等待在 stdin 上读取某些内容(因为它没有感知到已传递任何文件名)。

    可移植地,这种行为记录在 POSIX 中:

    以下两种类型的参数中的任何一种都可以混合使用:

    • 文件:包含要读取的输入的文件的路径名,与程序中的模式集相匹配。如果未指定文件操作数,或者文件操作数为“-”,则应使用标准输入。
    • 赋值:以可移植字符集中的下划线或字母字符开头的操作数(参见 IEEE Std 1003.1-2001 的基本定义卷中的表,第 6.1 节,可移植字符集),后跟一系列下划线、数字、和可移植字符集中的字母,后跟“=”字符,应指定变量分配而不是路径名。

    因此,可移植地,您有几个选项(#1 可能是干扰最小的):

    1. 使用awk ... ./my=file,它回避了这一点,因为.它不是“可移植字符集中的下划线或字母字符”。
    2. 使用 .将文件放在标准输入上awk ... < my=file。但是,这不适用于多个文件。
    3. 暂时对文件进行硬链接,然后使用它。您可以执行类似的操作ln my=file my_file,然后my_file正常使用。不会执行复制,两个文件将由相同的数据和 inode 元数据支持。使用它后,删除创建的链接是安全的,因为对 inode 的引用数仍将大于 0。
    • 22
  2. Best Answer
    Stéphane Chazelas
    2018-12-23T14:34:03+08:002018-12-23T14:34:03+08:00

    正如Chris 所说,表单的参数variablename=anything被视为变量赋值(在处理参数时执行,而不是在语句之-v var=value​​前执行的(较新的)参数)而不是输入文件名。BEGIN

    这在以下方面可能很有用:

    awk '{print $1}' FS=/ RS='\n' file1 FS='\n' RS= file2
    

    您可以在其中指定不同的FS/RS每个文件。它也常用于:

    awk '!file1_processed{a[$0]; next}; {...}' file1 file1_processed=1 file2
    

    哪个是更安全的版本:

    awk 'NR==FNR{a[$0]; next}; {...}' file1 file2
    

    file1(如果为空则不起作用)

    但是,当您的文件名称中包含=字符时,就会出现问题。

    现在,只有当第一个剩下的=是一个有效的awk变量名时,这才是一个问题。

    构成有效变量名的 inawk比 in 更严格sh。

    POSIX 要求它类似于:

    [_a-zA-Z][_a-zA-Z0-9]*
    

    只有可移植字符集的字符。但是,/usr/xpg4/bin/awkSolaris 11 至少在这方面不兼容,并且允许在变量名中使用语言环境中的任何字母字符,而不仅仅是 a-zA-Z。

    因此,像x+y=fooor =baror之类的参数./foo=bar仍被视为输入文件名,而不是赋值,因为第一个参数的剩余部分=不是有效的变量名。类似的参数Stéphane=Chazelas.txt可能会也可能不会,取决于awk实现和语言环境。

    这就是为什么使用 awk,建议使用:

    awk '...' ./*.txt
    

    代替

    awk '...' *.txt
    

    例如,如果您不能保证txt文件名不包含=字符,则可以避免该问题。

    另外,请注意,-vfoo=bar.txt如果您使用以下参数,可能会将类似的参数视为一个选项:

    awk -f file.awk -vfoo=bar.txt
    

    (也适用于1.28.0 之前awk '{code}' -vfoo=bar.txt的busybox 版本,请参阅相应的错误报告)。awk

    同样, using./*.txt可以解决这个问题(使用./前缀也有助于一个名为的文件-,否则它被awk理解为意味着标准输入)。

    这也是为什么

    #! /usr/bin/awk -f
    

    shebangs并没有真正起作用。虽然var=value可以通过在语句中修复ARGV值(添加./前缀)来解决这些问题:BEGIN

    #! /usr/bin/awk -f
    BEGIN {
      for (i = 1; i < ARGC; i++)
        if (ARGV[i] ~ /^[_[:alpha:]][_[:alnum:]]*=/)
          ARGV[i] = "./" ARGV[i]
    }
    # rest of awk script
    

    这对选项没有帮助,因为那些是由脚本awk而不是awk脚本看到的。

    使用该./前缀的一个潜在外观问题是它以 结尾,但如果您不想要它FILENAME,您可以随时使用它来剥离它。substr(FILENAME, 3)

    GNU 实现通过它的选项awk修复了所有这些问题。-E

    之后-E,gawk 只需要awk脚本的路径(其中-仍然表示标准输入),然后只需要输入文件路径的列表(在那里,甚至-没有被特殊处理)。

    它专为:

    #! /usr/bin/gawk -E
    

    shebangs,其中参数列表始终是输入文件(请注意,您仍然可以在语句中自由编辑该ARGV列表)。BEGIN

    您还可以将其用作:

    gawk -e '...awk code here...' -E /dev/null *.txt
    

    我们使用-E空脚本 ( /dev/null) 只是为了确保*.txt之后的那些始终被视为输入文件,即使它们包含=字符。

    • 22
  3. Sergiy Kolodyazhnyy
    2018-12-23T14:11:40+08:002018-12-23T14:11:40+08:00

    引用gawk 文档(添加注意重点):

    命令行上的任何附加参数通常被视为要按指定顺序处理的输入文件。但是,具有 var=value 形式的参数将值 value 分配给变量 var——它根本不指定文件。

    为什么命令停止并等待?因为在表格awk 'processing_script_here' my=file.txt 中没有由上述定义指定的文件 -my=file.txt被解释为变量赋值,如果没有定义文件awk将读取标准输入(也很明显,strace这表明此类命令中的 awk 正在等待read(0,'...)系统调用。

    这也记录在POSIX awk 规范中,请参阅操作数部分和其中的分配部分)

    变量赋值在 /etc/passwd 中的每一行打印的awk '{print foo}' foo=bar /etc/passwd值中很明显。foo但是,指定./foo=bar或完整路径确实有效。

    请注意,运行strace和awk '1' foo=bar检查cat foo=bar表明这是特定于 awk 的问题,并且 execve 确实将文件名显示为传递的参数,因此在这种情况下,shell 与 env 变量分配无关。

    另外,请注意这awk '...script...' foo=bar不会导致shell创建环境变量,因为环境变量分配应该在命令之前生效。请参阅POSIX Shell Grammar Rules,第 7 点。此外,这可以通过以下方式验证awk '{print ENVIRON["foo"]}' foo=bar /etc/passwd

    • 4

相关问题

  • 根据第一个逗号之前的匹配删除重复行数

  • 在另一个文件之后逐行追加行

  • 如何删除两行之间的单行

  • 重新排列字母并比较两个单词

  • 多行文件洗牌

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve