bash-用新行替换空间


70

如何在输入中用换行符替换空格:

/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5 等等...

要获得以下内容:

/path/to/file
/path/to/file2
/path/to/file3
/path/to/file4
/path/to/file5

注意

我正在发布此问题以帮助其他用户,在我开始键入此问题之前,要在UNIX SE上找到有用的答案并不容易。之后,我发现了以下内容:

相关问题

如何查找并替换为新行?



ls / path / to / | xargs回声| SED的/ \ S \ + / \ N / G'
SD。

Answers:



20

在这种情况下,我将使用printf:

printf '%s\n' /path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5

如果其中一个路径有空格,则可以引用该文件路径,以防止在空格上将其分割:

printf '%s\n' /path/to/file '/path/to/file with spaces' /path/to/another/file

总体而言,对文本进行转换tr是您最好的选择,如现有答案所述。


1
未来的简短说明:感谢您发布此解决方案,与使用“ echo”相比,它对我来说非常可靠。
Liesmith

5

假设您有一个以空格为分隔符的字符串:

newline_separated=${space_separated// /$'\n'}

但是,您可能会问错问题。(不一定,例如,这可能会在makefile中出现。)用空格分隔的文件名列表实际上并不起作用:如果其中一个文件名包含空格,该怎么办?

如果程序接收文件名作为参数,请不要使用空格将它们连接在一起。用于"$@"一一访问它们。尽管echo "$@"打印的参数之间带有空格,但这是由于echo:它打印的参数带有空格作为分隔符。somecommand "$@"将文件名作为单独的参数传递给命令。如果要在单独的行上打印参数,则可以使用

printf '%s\n' "$@"

如果您确实有用空格分隔的文件名,并且希望将它们放在数组中以对其进行处理,则可以使用不带引号的变量扩展来拆分字符上的值IFS(您需要使用禁用通配符扩展set -f,否则使用glob模式将在值中扩展):

space_separated_list='/path/to/file1 /path/to/file2 /path/to/file3'
IFS=' '; set -f
eval "array=(\$space_separated_list)"
for x in "${array[@]}"; do 

您可以将其封装在一个函数中,该函数可以还原-f设置和设置IFS完成后的值:

split_list () {
  local IFS=' ' flags='+f'
  if [[ $- = *f* ]]; then flags=; fi
  set -f
  eval "$1=($2)"
  set $flags
}
split_list array '/path/to/file1 /path/to/file2 /path/to/file3'
for x in "${array[@]}"; do 

更改此答案的正确答案。我认为研究我如何到达以空格分隔的列表并以另一种方式检索该信息是更正确的。如果您评论一下您的片段,告诉我们像本地var IFS或$-= f条件这样的事情,这对像我这样的学习者来说将很酷。几次使用bash的人都不知道这种事情。
laconbass 2014年

@laconbass我添加了简短的解释。查找set -fIFS在bash的手册,如果你想所有的细节。另请参见unix.stackexchange.com/questions/16192/…–
Gilles

@Guilles简短的解释对我来说足够了,我认为对其他许多人来说也是如此。
泰恩

IFS在本地设置不会生效
Eliran Malka

@EliranMalka我不知道你是什么意思。如果脚本的行为不符合您的预期,则可以在此处提出问题。
吉尔斯

4

务实,使用sed !!

sed 's/\s\+/\n/g' file

上面说用换行符(\ n)替换一个或多个空格字符(\ s +)

这或多或少:

'substitute /one space or more/ for /newline/ globally'

1
用替代替换更改,这实际上是s的代表!
罗布

@Rob谢谢,记住您可以编辑其他答案。
MGP

1
如果文本之间有多个空格,则会出现空白行。您需要在\ s后面添加一个“ +”号,以表示您要匹配至少一个与正好一个空格相对应的空格。即。SED的/ \ S + / \ N / G'
DarkHeart

4

作为tr@laconbass 的替代方法,您还可以xargs在这种情况下使用:

echo "/path/to/file /path/to/file2 /path/to/file3 /path/to/file4  /path/to/file5"\
| xargs -n1

好处是它甚至可以在多个空白中工作,而空白tr却不能。


0

这是我的做法:

echo "/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5" | sed 's/ /\
'/g

注意sed命令中反斜杠后使用Enter键。


什么prons和缺点有sedtr
laconbass 2013年

您的舒适度:-)我想您可以做更多的事情,sed因为它是编辑器,而不是简单地翻译字符。
unxnut 2013年

4
sed可以做更多的事情,但这完全是矫kill过正。tr是完成此工作的正确工具,但是sed稍后会更方便地了解和正则表达式!
罗布

0

假设该行位于名为的变量中,则是另一种方法line

for path in $line;do echo $path;done

这利用了以下事实:Bash默认在空白处拆分其参数,并且默认情况下echo在其输入后添加换行符。


在发布此问题之前,我在ubuntu系统上尝试了此操作,但无法使其正常工作。
laconbass

0
echo word1 word2 ... | sed -e 'y/ /\n/;P;D'

是将单行分隔的单词转换为换行符的另一种方法。


-1

以下脚本易于理解且易于使用。

cat filename | tr ' ' '\n' | tee filename

2
您的答案(tr)的实质与接受的答案相同。除了您的答案还有以下问题:a)该命令没有缩进4个空格(-> markdown布局)b)您的使用cat是无用的(可以将其替换为< filename tr ' ' '\n')。c)您的输出文件名与输入文件名相同。这样您就可以创建数据竞赛。
maxschlepzig

1
除了maxschlepzig的正确分析之外,这不是脚本,而是一堆具有硬编码名称的连接命令(因为脚本希望有一个标头指定要使用的shell,并使用两个参数来指定in和output)。除了我家中三分之二的人,很难理解。也许这不是代表性的,但是请记住,您自己理解的东西(在这种情况下您认为自己理解的东西)看起来总是很容易的。
Anthon
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.