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

时间:2014-04-12 07:38:09

标签: 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

如果我在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,那么空间就会出现空格:

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

在其他计算机(MacOS)中,我解决了这个问题,使用此命令IFS=$'\n'将IFS更改为分界线,但在我的家用计算机(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

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

2 个答案:

答案 0 :(得分:2)

根本不需要循环。这应该做你想要的:

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

如果你真的想循环结果,you should use while rather than 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字符的问题,可能是您的Ubuntu计算机上的/bin/sh不支持$'' bashism

答案 1 :(得分:2)

您可以将IFS设置为这样的换行符:

IFS="
"

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

这个shell是否恰好理解$'\n'并不是你应该依赖的东西。如果您想使用$'\n'更改,请将其更改为#!/bin/bash或其他一个贝壳..


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


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

如果与常规练习相混合,取消设置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