You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Emacs编辑含here document的Shell脚本出现unexpected end of file错误的解决方法

Fixing "unexpected end of file" Error with Emacs and Shell Here Documents

I’ve run into this exact issue before—Shell here documents are super picky about their closing markers! The root problem is that the closing marker (like EOF) must be completely left-aligned, with no leading spaces or indentation whatsoever, and Emacs’ default auto-indent behavior tends to add spaces to that line, which breaks things. Here are a few solid ways to keep using Emacs for your shell scripts without hitting this error:

1. Manually Ensure the Closing Marker is Left-Aligned

The simplest quick fix is to just make sure your here document’s closing tag sits flush against the left margin, no matter how indented the surrounding code is. For example:

if [ -f /etc/os-release ]; then
    cat <<EOF
=== System Information ===
OS: $(grep PRETTY_NAME /etc/os-release | cut -d= -f2)
Hostname: $(hostname)
EOF
fi

Even though the cat command is indented under the if block, the final EOF has to be completely unindented. Emacs might try to auto-indent it as you type—just hit backspace until it’s all the way left.

2. Enable Emacs’ Shell Here Doc Indent Mode

Emacs’ built-in sh-mode has a dedicated mode to handle here documents correctly. This will let you keep auto-indenting your code, while automatically ensuring the closing marker stays left-aligned:

  1. Open your shell script (Emacs should auto-enter sh-mode for .sh files; if not, run M-x sh-mode).
  2. Enable the mode manually with M-x sh-here-doc-indent-mode.
  3. To make this permanent for all shell scripts, add this to your ~/.emacs or ~/.emacs.d/init.el configuration file:
    (add-hook 'sh-mode-hook 'sh-here-doc-indent-mode)
    

Once enabled, Emacs will indent the content inside your here document nicely, but will never add leading spaces to the closing marker.

3. Use <<- for Tab-Indented Closing Markers

If you prefer to keep your closing marker indented (to match the rest of your code), you can use the <<- syntax instead of <<—this allows the closing marker to have leading tab characters (not spaces). To make this work with Emacs:

  1. Modify your here document to use <<-:
    if [ -f /etc/os-release ]; then
        cat <<-EOF
        === System Information ===
        OS: $(grep PRETTY_NAME /etc/os-release | cut -d= -f2)
        Hostname: $(hostname)
        EOF
    fi
    
  2. Set Emacs to use tabs instead of spaces for indentation in sh-mode. Either run M-x set-variable and set indent-tabs-mode to t for the current buffer, or add this to your config to make it default:
    (add-hook 'sh-mode-hook (lambda () (setq indent-tabs-mode t)))
    

The - in <<- tells the shell to ignore any leading tabs before the closing marker, so your indentation stays clean and the script runs without errors.

Why Nano Works but Emacs Doesn’t

Nano doesn’t auto-indent code by default, so you probably didn’t add any leading spaces to the closing marker when editing there. Emacs’ auto-indent feature, while great for most code, doesn’t know about Shell’s strict here document rules out of the box—hence the "unexpected end of file" error when it adds spaces to that closing line.

内容的提问来源于stack exchange,提问作者computronium

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 14:37:35