首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >倒车线路组

倒车线路组
EN

Stack Overflow用户
提问于 2013-09-08 13:43:09
回答 4查看 179关注 0票数 1

我正在寻找一种优雅的方法来逆转文本文件内容,不仅仅是逐行(如tac所做的),而是逐行(节)。以下例子应是详尽无遗的:

原始文件内容:

代码语言:javascript
复制
--------    -----
    time        |
--------        | 
10:00:00        |--- section 1 
10:00:10        | 
10:00:20        |
--------    -----
--------    -----
    time        |
--------        | 
10:01:00        |--- section 2 
10:01:10        | 
10:01:20        |
--------    -----

减少的产出:

代码语言:javascript
复制
--------    -----
    time        |
--------        | 
10:01:00        |--- section 2 
10:01:10        | 
10:01:20        |
--------    -----
--------    -----
    time        |
--------        | 
10:00:00        |--- section 1 
10:00:10        | 
10:00:20        |
--------    -----
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-09-08 13:50:12

一个awk可以做到:

代码语言:javascript
复制
awk '{a[i++]=$0};/-----/{++j};j==3{t="";for(k=0;k<i;++k)t=t a[k]"\n";b[++l]=t;i=j=0}END{for(i=l;i;--i)printf "%s", b[i]}' file

输出:

代码语言:javascript
复制
----------------------------------------------------------------
date        time        hostname    cpu     ram     /       /opt
----------------------------------------------------------------
2013/09/08  15:40:00    server1     20%     30%     50%     70%
2013/09/08  15:40:00    server2     15%     21%     49%     72%
2013/09/08  15:40:00    server3     20%     40%     40%     75%
----------------------------------------------------------------
----------------------------------------------------------------
date        time        hostname    cpu     ram     /       /opt
----------------------------------------------------------------
2013/09/08  15:35:00    server1     15%     30%     50%     70%
2013/09/08  15:35:00    server2     18%     21%     49%     72%
2013/09/08  15:35:00    server3     15%     40%     40%     75%
----------------------------------------------------------------
----------------------------------------------------------------
date        time        hostname    cpu     ram     /       /opt
----------------------------------------------------------------
2013/09/08  15:30:00    server1     20%     30%     50%     70%
2013/09/08  15:30:00    server2     10%     21%     49%     72%
2013/09/08  15:30:00    server3     15%     40%     40%     75%
----------------------------------------------------------------

另一种可能排除无效数据的更安全的变化是:

代码语言:javascript
复制
awk '/^-----+$/{++j};!j{next};{a[i++]=$0}j==3{t="";for(k=0;k<i;++k)t=t a[k]"\n";b[++l]=t;i=j=0}END{for(i=l;i;--i)printf "%s", b[i]}' file

另一个以行数为基础的:

代码语言:javascript
复制
awk '{a[i++]=$0}i==7{t="";for(k=0;k<i;++k)t=t a[k]"\n";b[++l]=t;i=0}END{for(i=l;i;--i)printf "%s", b[i]}' file

简单一点:

代码语言:javascript
复制
awk '{a[i++]=$0}i==7{t="";for(i=0;i<7;++i)t=t a[i]"\n";b[++j]=t;i=0}END{for(;j;--j)printf "%s", b[j]}' file

另一种简单的方法是在Bash中使用相同的概念:

代码语言:javascript
复制
( IFS=$'\n'; while read -r A[I++]; do [[ I -eq 7 ]] && { B[++J]="${A[*]}"; I=0; }; done; for ((;J;--J)); do echo "${B[J]}"; done; ) < file

Ruby的另一个真正的衬线:

代码语言:javascript
复制
ruby -e '$stdin.readlines().each_slice(7).entries.reverse.each { |b| puts b; }' < file
票数 2
EN

Stack Overflow用户

发布于 2013-09-09 10:45:49

您可以使用标准命令,使用临时文件来完成此操作。在我看来,它更短、更易读:)

代码语言:javascript
复制
split -a 4 -d -l 7 data.txt block
cat $(ls -r block*) > reversed-data.txt
rm block*

对于split命令:

  • -a 4代表4个数字的后缀
  • -d表示数字后缀
  • -l 7将源文件拆分成这几行
  • data.txt文件要读取
  • 临时文件的block前缀

split为每一行生成一个临时文件,名为blocknnnn,其中nnnn是序列号。cat将这些块放在一起,并按照ls -r给出的顺序排列文件列表。

优点:文件没有加载到内存中,因此在这方面没有限制其大小。

缺点:将数据的完整副本复制到磁盘,因此需要两倍的空间。

票数 1
EN

Stack Overflow用户

发布于 2013-09-08 14:08:26

awk绝对是正确的选择,但是这里有一个bash替代方案:

代码语言:javascript
复制
#!/bin/bash

separator='----------------------------------------------------------------' # each block must end with a separator
blockSeparators=3 # number of separators in each block. Could be 1 as well

dataArr=()
current=0
subCounter=0
while read -r curLine; do
    dataArr[current]+=$curLine$'\n'
    if [[ $curLine == "$separator" ]]; then
        (( ++subCounter == blockSeparators )) && (( current++ , subCounter=0 ))
    fi
done < file.txt

for (( i=${#dataArr[@]}; i>=0; i-- )); do
    echo -n "${dataArr[i]}"
done

如果你知道你所有的区块都有7行:

代码语言:javascript
复制
#!/bin/bash

blockLines=7

dataArr=()
current=0
lineCounter=0
while read -r curLine; do
    dataArr[current]+=$curLine$'\n'
    (( ++lineCounter == blockLines )) && (( current++ , lineCounter=0 ))
done < file.txt

for (( i=${#dataArr[@]}; i>=0; i-- )); do
    echo -n "${dataArr[i]}"
done

但如前所述,请使用awk解决方案。) Bash不是做这种操作的正确方法:)

编辑:

更短的巴什!

代码语言:javascript
复制
blockSize=7

readarray lines < file.txt
for (( i=${#lines[@]}-blockSize; i>=0; i-=blockSize )); do
    ( IFS=''; echo -n "${lines[*]:i:blockSize}" )
done
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18684359

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档