IFS=$'\n' 不会将 IFS 更改为隔断线

dgn*_*nin 1 shell

我编写了下一个测试 shell 脚本:

#!/bin/sh
IFS=$'\n'
for d in `find . -name *.cue -print0 | xargs -0 -n1 dirname | sort --unique`
do
  unset IFS
  echo "$d"
  IFS=$'\n'
done
unset IFS
Run Code Online (Sandbox Code Playgroud)

如果我在 bash 中执行条件的 find 命令,我会得到如下内容:

./[FLAC] Destination Goa - The Sixth Chapter (CD)/CD2
./[FLAC] Eat Static - Implant - (CD)
./[FLAC] Elysium - Dance For The Celestial Beings (CD)
./[FLAC] Elysium - Monzoon 1996 (CD)
./[FLAC] Etnica - The Juggeling Alchemists Under The Black Light
Run Code Online (Sandbox Code Playgroud)

(包含cue文件的文件夹的名称)

在 shell 脚本中,我想循环使用每个文件夹,但是,当然,如果我不重新定义 IFS,则事件会以空格分隔:

Experience
4
./[FLAC]
VA
-
Trancentral
Five
A
Sonic
Initiation
./[FLAC]
VA
-
Trancentral
Run Code Online (Sandbox Code Playgroud)

在其他计算机(MacOS)中,我解决了这个问题,使用此命令将 IFS 更改为断线,IFS=$'\n'但在我的家用计算机(Ubuntu Linux)中,循环用“n”中断出现:

tra
ce - A Trip To Psychedelic Tra
ce (CD)/CD1
./[FLAC] VA - Ta
tra
ce - A Trip To Psychedelic Tra
ce (CD)/CD2
./[FLAC] VA - Tech
o Tra
ce Ma
Run Code Online (Sandbox Code Playgroud)

您知道发生了什么以及为什么计算机之间的行为不同吗?谢谢。

Scr*_*zer 6

您可以将 IFS 设置为换行符,如下所示:

IFS="
"
Run Code Online (Sandbox Code Playgroud)

$'\n'是 ksh93/bash/zsh 语法,但不是 POSIX 语法。在大多数当前系统上#!/bin/sh指向 POSIX shell(尽管 POSIX 并不要求这样做,Solaris 9,10 是一个例外)。

$'\n'您不应该依赖该 shell 是否能够理解。如果你想使用$'\n'改变你的 shebang#!/bin/bash或其他 shell 之一..


在 Ubuntu 和 debian linux 及其衍生版本上/bin/sh指向dash. 对于其他一些发行版,它指向/bin/bash --posix(posix 模式下的 bash)...


另一点需要注意的是,如果取消设置 IFS,您不会返回到之前的状态,即包含空格、制表符和换行符的 IFS。通过取消设置 IFS ,将完成字段分割,就好像 IFS 包含空格、制表符和换行符一样,所以一切看起来都很好。

然而,如果与常规做法混合使用,取消 IFS 的设置可能会导致并发症

  unset IFS        # Unset the IFS variable so it does not exist
  oldIFS=$IFS      # The old state is supposedly saved
  IFS=:            # IFS is set to some string
  IFS=$oldIFS      # Now IFS is set to the empty string, which means no field 
                   # splitting is performed at all
Run Code Online (Sandbox Code Playgroud)