Skip to content

转置文件

描述

给定一个文件 file.txt,转置它的内容。

你可以假设每行列数相同,并且每个字段由 ' ' 分隔。

示例

输入:file.txt

name age
alice 21
ryan 30
输出
name alice ryan
age 21 30

题解

分析

这道题要是用matlab那就是一步到位,不过用shell也不难,只要完成以下两步即可。

  1. 获取文件的列数
  2. 按列读取文件,并按行输出

实现1

wc可以获取文件的行数、单词数和字符数,由于文件按二维数组形式存储,所以列数就等于单词数除以行数 words / lines

wc file.txt的输出格式为lines words chars file.txt, 然后通过awk 计算 words 与 lines 相除之商就是行数。

知道了列数,接下来就是按列输出,cut -d' ' -f $i file.txt可以打印按空格分隔的第 i 列,使用echo直接输出便是按行输出了。

# Read from the file file.txt and print its transposed content to stdout.

# 1. 获取列数
col=$(wc file.txt | awk '{print $2 / $1}')

# 2. 按列打印
for i in `seq 1 $col`
do
    echo `cut -d' ' -f $i file.txt`
done

echo 不加引号

此处echo不对输出内容加引号,就会在输出时自动将换行符\n替换为空格

实现2

对于按列读取,也可以使用awk {print $i}打印第 i 列,然后通过xargs按行输出

# Read from the file file.txt and print its transposed content to stdout.

# 1. 获取列数
col=$(wc file.txt | awk '{print $2 / $1}')

# 2. 按列打印
for i in `seq 1 $col`
do
    awk -v col="$i" '{print $col}' file.txt |xargs
done

awk 使用变量

awk调用shell变量有点麻烦,可以通过-v name="$var"定义awk可用的变量

实现3

对于获取列数,除了以上方法外,还可以通过head结合wc,读取首行文本并计算单词数

col=$(head -1 file.txt | wc -w)

当然,head可以,tail自然也行,就不赘述了。

小结

本题主要考察文件读写操作,涉及指令主要包括echo, awk, wchead, xargs.

运用到的两个小技巧:

  1. echo 不加引号会自动将换行符转为空格
  2. awk 通过-v name="$var"可以调用 shell 变量