IFS = $ '\\ N' 不改变IFS到特征线(IFS=$'\\n

2019-10-19 20:47发布

我写的下一个测试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

如果我在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

(含线索文件的文件夹的名称)

在shell脚本我想用这个文件夹中的每一个,但是,当然,如果我不重新定义IFS用空格occurreances中断循环:

Experience
4
./[FLAC]
VA
-
Trancentral
Five
A
Sonic
Initiation
./[FLAC]
VA
-
Trancentral

在其他计算机(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

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

Answer 1:

您可以设置IFS对这样一个新行:

IFS="
"

$'\n'是ksh93的/庆典/ zsh中的语法,但它不是POSIX语法。 在大多数当前的系统#!/bin/sh指向POSIX外壳(虽然这不是由POSIX和Solaris 9,10要求是个例外)。

无论是外壳碰巧了解$'\n'是不是你应该依靠。 如果你想使用$'\n'改变你的家当以#!/bin/bash或其他壳之一..


在Ubuntu和Debian Linux和衍生品/bin/shdash 。 与其他一些发行它指向/bin/bash --posix (Bash和POSIX模式)...


还有一点要注意的是,如果你没有设置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


Answer 2:

你不需要循环的。 这应该做你想要什么:

find . -name *.cue -print0 | xargs -0 -n1 dirname | sort --unique

如果你真的要循环的结果, 你应该使用while不是for

while IFS= read -r line; do
    printf '%s\n' "$line"
done < "$file"

要么

my_script | while IFS= read -r line; do
    printf '%s\n' "$line"
done

让我们回到关于字面分裂的问题n字符,它可能是/bin/sh你的Ubuntu机器上不支持$'' bashism 。



文章来源: IFS=$'\\n' doesn't change IFS to breaklines
标签: shell