【发布时间】:2011-02-15 09:11:08
【问题描述】:
我想将ls -1 的结果合并到一行中,并用我想要的任何内容进行分隔。
我可以使用任何标准的 Linux 命令来实现这一点吗?
【问题讨论】:
标签: linux bash shell parsing merge
我想将ls -1 的结果合并到一行中,并用我想要的任何内容进行分隔。
我可以使用任何标准的 Linux 命令来实现这一点吗?
【问题讨论】:
标签: linux bash shell parsing merge
如果您的 xargs 版本支持 -d 标志,那么这应该可以工作
ls | xargs -d, -L 1 echo
-d 是分隔符标志
如果你没有-d,那么你可以试试下面的
ls | xargs -I {} echo {}, | xargs echo
第一个 xargs 允许您指定分隔符,在此示例中为逗号。
【讨论】:
-d 使用 GNU xargs 指定输入分隔符,因此不起作用。第二个示例展示了与此处的其他解决方案相同的问题,即末尾的杂散定界符。
编辑:如果您希望分隔符为逗号,只需“ls -m”即可
啊,强大而简单!
ls -1 | tr '\n' ','
将逗号“,”更改为您想要的任何内容。请注意,这包括“尾随逗号”
【讨论】:
\n,这也将替换它。
ls -1 | tr "\\n" "," | sed 's/\(.*\),/\1/'
sed 使用结束标记字符可能会更有效一些:ls -1 | tr "\\n" "," | sed 's/,$//'; echo ''
tr 之后使用sed 似乎只是删除最后一个符号似乎不合理。我选择ls -1 | tr '\n' ',' | head -c -1
你可以使用:
ls -1 | perl -pe 's/\n$/some_delimiter/'
【讨论】:
为了避免 tr 潜在的换行混淆,我们可以在 ls 中添加 -b 标志:
ls -1b | tr '\n' ';'
【讨论】:
这用换行符替换最后一个逗号:
ls -1 | tr '\n' ',' | sed 's/,$/\n/'
ls -m 在屏幕宽度字符处包含换行符(例如第 80 个)。
主要是 Bash(只有 ls 是外部的):
saveIFS=$IFS; IFS=$'\n'
files=($(ls -1))
IFS=,
list=${files[*]}
IFS=$saveIFS
在 Bash 4 中使用 readarray(又名 mapfile):
readarray -t files < <(ls -1)
saveIFS=$IFS
IFS=,
list=${files[*]}
IFS=$saveIFS
感谢 gniourf_gniourf 的建议。
【讨论】:
mapfile (Bash ≥4) 作为:mapfile -t files < <(ls -1)。无需摆弄IFS。而且它也更短。
IFS加入字段:saveIFS=$IFS; IFS=,; list=${files[*]}; IFS=$saveIFS。或者,如果您想要一个包含多个字符的分隔符,请使用另一种方法。
随便打
mystring=$(printf "%s|" *)
echo ${mystring%|}
【讨论】:
|、@camh 产生影响。
bash 和 gnu coreutils printf
printf -v 仅适用于 bash,而提供的答案适用于许多 shell 类型。
|,前提是两行都使用:printf -v mystring "%s|" * ; echo ${mystring%|}。
设置IFS 和使用"$*" 的组合可以为所欲为。我正在使用一个子shell,所以我不会干扰这个shell的$IFS
(set -- *; IFS=,; echo "$*")
要捕获输出,
output=$(set -- *; IFS=,; echo "$*")
【讨论】:
set 工作原理的信息?对我来说有点像巫毒教。对man set 的浅浅浏览也没有给我带来太多信息。
set 一堆参数但没有选项,它会设置位置参数($1, $2, ...)。 -- 可以保护set,以防第一个参数(或本例中的文件名)碰巧以破折号开头。请参阅help set 中对-- 选项的描述。我发现位置参数是一种处理事物列表的便捷方式。我也可以用一个数组来实现这个:output=$( files=(*); IFS=,; echo "${files[*]}" )
type set 会告诉你的那样,set is a shell builtin。所以,man set 无济于事,但help set 会。答案:“-- 将任何剩余的参数分配给位置参数。”
set -- * 之后。将* 的扩展延迟一层,您可以获得正确的输出,而无需子外壳:IFS=',' eval echo '"$*"'。当然这会改变位置参数。
类似于第一个选项,但省略了尾随分隔符
ls -1 | paste -sd "," -
【讨论】:
ls -1 | paste -s -d ":" -不确定这是否适用于所有版本的粘贴
paste 默认获取-(标准输入),至少在我的paste (GNU coreutils) 8.22 上。
"\0"指定空分隔符,所以paste -sd "\0" -对我有用!
ls 连接到管道时会产生一列输出,因此-1 是多余的。
这是另一个使用内置 join 函数的 perl 答案,它不会留下尾随分隔符:
ls | perl -F'\n' -0777 -anE 'say join ",", @F'
不起眼的-0777 让perl 在运行程序之前读取所有输入。
不留下尾随分隔符的 sed 替代方案
ls | sed '$!s/$/,/' | tr -d '\n'
【讨论】:
我觉得这个不错
ls -1 | awk 'ORS=","'
ORS 是“输出记录分隔符”,所以现在您的行将用逗号连接。
【讨论】:
" OR ")
此命令适用于 PERL 爱好者:
ls -1 | perl -l40pe0
这里的 40 是空格的八进制 ascii 代码。
-p 将逐行处理并打印
-l 将负责用我们提供的 ascii 字符替换尾随的 \n。
-e 是通知 PERL 我们正在执行命令行。
0 表示实际上没有要执行的命令。
perl -e0 等同于 perl -e ' '
【讨论】:
不要重新发明轮子。
ls -m
它就是这么做的。
【讨论】:
ls -m 和tr 删除逗号后的空格,你会这样做ls -m | tr -d ' '
sed 's/, /,/g
ls 具有选项-m 以使用逗号和空格", " 分隔输出。
ls -m | tr -d ' ' | tr ',' ';'
将此结果传送到tr 以删除空格或逗号将允许您再次将结果传送到tr 以替换分隔符。
在我的示例中,我将分隔符 , 替换为分隔符 ;
将; 替换为您喜欢的任何一个字符分隔符,因为 tr 仅考虑您作为参数传入的字符串中的第一个字符。
【讨论】:
sed -e :a -e '/$/N; s/\n/\\n/; ta' [filename]
解释:
-e - 表示要执行的命令:a - 是一个标签/$/N - 定义当前行和 (N) 下一行的匹配范围
@ 987654326@ - 将所有 EOL 替换为 \nta; - 如果匹配成功则转到标签 a
取自my blog。
【讨论】:
一般解析lsis not advised,所以另一种更好的方法是使用find,例如:
find . -type f -print0 | tr '\0' ','
或者使用find和paste:
find . -type f | paste -d, -s
对于一般连接多行(与文件系统无关),请检查:Concise and portable “join” on the Unix command-line。
【讨论】:
您可以使用 chomp 将多行合并为单行:
perl -e 'while () { if (/\$/ ) { chomp; } print ;}' bad0 >test
if语句中加入换行条件,可以是特殊字符,也可以是任意分隔符。
【讨论】:
看起来答案已经存在。
如果你愿意
a, b, c 格式,使用ls -m (Tulains Córdova’s answer)
或者如果你想要a b c格式,使用ls | xargs(Chris J’s answer的简化版)
或者,如果您想要任何其他分隔符,例如 |,请使用 ls | paste -sd'|'(Artem’s answer 的应用程序)
【讨论】:
除了 majkinetor 的回答之外,这里是删除尾随分隔符的方法(因为我还不能在他的回答下发表评论):
ls -1 | awk 'ORS=","' | head -c -1
只需删除与分隔符一样多的尾随字节即可。
我喜欢这种方法,因为我可以使用多字符分隔符 + awk 的其他好处:
ls -1 | awk 'ORS=", "' | head -c -2
编辑
正如 Peter 所注意到的,本机 MacOS 版本的 head 不支持负字节数。然而,这很容易解决。
首先,安装coreutils。 “GNU Core Utilities 是 GNU 操作系统的基本文件、shell 和文本操作实用程序。”
brew install coreutils
MacOS 提供的命令也使用前缀“g”安装。例如gls。
完成此操作后,您可以使用具有负字节数的ghead,或者更好地使用别名:
alias head="ghead"
【讨论】:
sed 方式,
sed -e ':a; N; $!ba; s/\n/,/g'
# :a # label called 'a'
# N # append next line into Pattern Space (see info sed)
# $!ba # if it's the last line ($) do not (!) jump to (b) label :a (a) - break loop
# s/\n/,/g # any substitution you want
注意:
这在复杂性上是线性的,在所有行都附加到 sed 的模式空间之后只替换一次。
@AnandRajaseka 的 answer 和其他一些类似的答案,例如 here,是 O(n²),因为每次将新行附加到模式空间时 sed 都必须进行替换。
比较,
seq 1 100000 | sed ':a; N; $!ba; s/\n/,/g' | head -c 80
# linear, in less than 0.1s
seq 1 100000 | sed ':a; /$/N; s/\n/,/; ta' | head -c 80
# quadratic, hung
【讨论】:
带有斜杠处理的快速 Perl 版本:
ls -1 | perl -E 'say join ", ", map {chomp; $_} <>'
解释一下:
【讨论】:
如果 Python3 是您的最爱,您可以这样做(但请解释一下为什么要这样做?):
ls -1 | python -c "import sys; print(','.join(sys.stdin.read().splitlines()))"
【讨论】:
上面的 Python 答案很有趣,但自己的语言甚至可以使输出变得漂亮:
ls -1 | python -c "导入系统;打印(sys.stdin.read().splitlines())"
【讨论】: