在Unix shell中反转一个文件

时间:2015-07-06 18:37:48

标签: bash shell unix

我有一个文件parse.txt

parse.txt包含以下内容

remo/hello/1.0,remo/hello2/2.0,remo/hello3/3.0,whitney/hello/1.0,julie/hello/2.0,julie/hello/3.0

我希望使用parse.txt将output.txt文件改为(从最后一个到第一个的顺序)

julie/hello/3.0,julie/hello/2.0,whitney/hello/1.0,remo/hello3/3.0,remo/hello2/2.0,remo/hello/1.0

我尝试过以下代码:

tail -r parse.txt 

8 个答案:

答案 0 :(得分:26)

您可以使用GNU Coreutils中令人惊讶的有用tac

tac -s "," parse.txt > newparse.txt
默认情况下,

tac会将文件“标记”为标准输出,从而反转这些行。通过使用-s标志指定分隔符,您可以根据需要简单地反转字段。

(您可能需要执行后处理步骤以使逗号正常运行,这可能是您管道中的另一个步骤。)

答案 1 :(得分:9)

我喜欢tac解决方案;它非常优雅,但正如Micah指出的那样,tac是GNU Coreutils的一部分,这意味着它在FreeBSD,OSX,Solaris等中默认不可用。

这可以在纯粹的bash中完成,无需外部工具。

#!/usr/bin/env bash

unset comma
read foo < parse.txt
bar=(${foo//,/ })
for (( count="${#bar[@]}"; --count >= 0; )); do
  printf "%s%s" "$comma" "${bar[$count]}"
  comma=","
done

这显然只根据您的示例输入处理一行。如果需要处理多行输入,可以将其包装成。

这里的逻辑是我们可以通过用空格替换逗号将输入转换为数组。当然,如果我们的输入数据包含空格,则必须进行调整。一旦我们有阵列,我们只需向后退一步,打印每条记录。

请注意,这不包括终止换行符。如果您需要,可以添加:

printf '\n'

作为最后一行。

答案 2 :(得分:7)

perl -F, -lane 'print join ",", reverse @F' parse.txt > output.txt

答案 3 :(得分:4)

您可以使用此awk命令:

awk -v RS=, '{a[++i]=$1} END{for (k=i; k>=1; k--) printf a[k] (k>1?RS:ORS)}' parse.txt
julie/hello/3.0,julie/hello/2.0,whitney/hello/1.0,remo/hello3/3.0,remo/hello2/2.0,remo/hello/1.0

答案 4 :(得分:4)

问题标记为,您提到tail -r表示您可能没有使用Linux(使用完整的GNU工具链),而是使用某些“真正的”Unix(BSD变体),例如

因此,tac命令不可用,但如问题中所述,tail -r是。所以你可以使用以下内容:

$ tr ',' '\n' < parse.txt | tail -r | tr '\n' ',' | sed 's/,$//'
julie/hello/3.0,julie/hello/2.0,whitney/hello/1.0,remo/hello3/3.0,remo/hello2/2.0,remo/hello/1.0
$ 

注意:

  • 这仅适用于包含一行的文件,因为我们依赖于将逗号转换为换行符并返回。如果有多行,则两者之间的换行符将被第二行tr转换为逗号。
  • 最后的sed是删除一个尾随的逗号,该逗号是从tail
  • 插入的尾随换行符转换而来的

答案 5 :(得分:2)

您可以使用任何语言来执行此操作

xargs ruby -e "puts ARGV[0].split(',').reverse.join(',')" < parse.txt

答案 6 :(得分:2)

使用tac模仿sed

tr , '\n' <parse.txt | sed '1!G; h; $!d' | paste -sd ,

或者,如果您没有paste

tr , '\n' <parse.txt | sed '1!G; h; $!d' | tr '\n' , | sed 's/,$//'

输出:

julie/hello/3.0,julie/hello/2.0,whitney/hello/1.0,remo/hello3/3.0,remo/hello2/2.0,remo/hello/1.0

答案 7 :(得分:-1)

反向可以通过tac(来自cat)完成。正如所评论的那样,这将颠倒OP所要求的线路。

tac filename

如果您逐行提供并且不是换行分隔符,而是字段分隔符,请tac,您仍可以,

echo "a,b,c" | tr '\n' ',' | tac -s "," | sed 's/,$/\n/'