【Shell牛客刷题系列】SHELL11 转置文件的内容:继续awk命令的升级打怪之旅



该系列是基于牛客Shell题库,针对具体题目进行查漏补缺,学习相应的命令。

刷题链接:牛客题霸-Shell篇。

该系列文章都放到专栏下,专栏链接为:《专栏:Linux》。欢迎关注专栏~

本文知识预告:

  • 首先简单学习了rs命令,这个命令不常用,了解即可;
  • 然后本文给出了五种方法,值得一提的是xargs命令转置的功能,以及方法四中添加数字用以排序的技巧。总的来说,这道题仍然是awk命令的扩展。


题目:SHELL11 转置文件的内容

写一个bash脚本来转置文本文件nowcoder.txt中的文件内容。文件中每行列数相同,并且每个字段由空格分隔。假设 nowcoder.txt 内容如下:

job salary
c++ 13
java 14
php 12

你的脚本应当输出(以词频升序排列):

job c++ java php

相关命令学习

rs命令

rs:reshape a data array

rs读取标准输入,将每行解释为数组中一行空白的分隔条目,根据选项转换数组,并将其写入标准输出。无参数时,它将流输入转换为便于终端查看的列格式,即如果长度(以字节为单位!).

-c[x] Input columns are delimited by the single character x. A missing x is taken to be ‘^I’.
-T Print the pure transpose of the input, ignoring any rows or cols specification.
-z Shrink column widths to fit the largest entries appearing in them.

具体细节,可以输入以下命令查看:

man rs

题目解决方案

方法一:简单粗暴的方法

a=$(cat nowcoder.txt | awk '{print $1}')
b=$(cat nowcoder.txt | awk '{print $2}')
echo $a
echo $b

方法二:awk+xargs转置

cNum=$(awk '{print NF}' nowcoder.txt | uniq)
for i in $(seq 1 $cNum); do
	cat nowcoder.txt | awk -v var=$i '{print $var}' | xargs
done

拆分步骤:

  1. 求出文件中的内容一共有多少列:
lucky@DESKTOP-VQ8KID4:~$ awk '{print NF}' nowcoder.txt | uniq
2
  1. 对于每一列,使用xargs命令输出,就可达到了转置的目的
lucky@DESKTOP-VQ8KID4:~$ cat nowcoder.txt | awk -v var=1 '{print $var}' | xargs
job c++ java php
lucky@DESKTOP-VQ8KID4:~$ cat nowcoder.txt | awk -v var=2 '{print $var}' | xargs
salary 13 14 12
  1. 然后遍历每一列的内容,将遍历得到的内容,按上面的方式输出即可:
cNum=$(awk '{print NF}' nowcoder.txt | uniq)
for i in $(seq 1 $cNum); do
	cat nowcoder.txt | awk -v var=$i '{print $var}' | xargs
done

方法三:awk命令搭配for循环

lucky@DESKTOP-VQ8KID4:~$ awk '{for(i=1;i<=NF;i++) a[i]=a[i]$i" "}END{for(x in a) print a[x]}' nowcoder.txt
job c++ java php
salary 13 14 12

方法四:awk添加数字,排序,直接转置

lucky@DESKTOP-VQ8KID4:~$ awk '$1="1."NR","$1,$2="2."NR","$2' nowcoder.txt | tr " " "\n" | sort -n | awk -F "," '{print $2}' | tr "\n" " " | awk -F" " '$5="\n"$5'
job c++ java php
salary 13 14 12

拆分步骤:

  1. 在每一个字符串前面加一个数据用于排序
lucky@DESKTOP-VQ8KID4:~$ awk '$1="1."NR","$1,$2="2."NR","$2' nowcoder.txt
1.1,job 2.1,salary
1.2,c++ 2.2,13
1.3,java 2.3,14
1.4,php 2.4,12
  1. 把数据拉长成一列
lucky@DESKTOP-VQ8KID4:~$ awk '$1="1."NR","$1,$2="2."NR","$2' nowcoder.txt | tr " " "\n"
1.1,job
2.1,salary
1.2,c++
2.2,13
1.3,java
2.3,14
1.4,php
2.4,12
  1. 对上面的数据,按第一列的数字进行排序
lucky@DESKTOP-VQ8KID4:~$ awk '$1="1."NR","$1,$2="2."NR","$2' nowcoder.txt | tr " " "\n" | sort -n
1.1,job
1.2,c++
1.3,java
1.4,php
2.1,salary
2.2,13
2.3,14
2.4,12
  1. 按照,分隔出两列,提取出第二列
lucky@DESKTOP-VQ8KID4:~$ awk '$1="1."NR","$1,$2="2."NR","$2' nowcoder.txt | tr " " "\n" | sort -n | awk -F "," '{print $2}'
job
c++
java
php
salary
13
14
12
  1. 把所有内容排成一行
lucky@DESKTOP-VQ8KID4:~$ awk '$1="1."NR","$1,$2="2."NR","$2' nowcoder.txt | tr " " "\n" | sort -n | awk -F "," '{print $2}' | tr "\n" " "
job c++ java php salary 13 14 12
  1. 以空格为分隔符,在第五列处进行换行
lucky@DESKTOP-VQ8KID4:~$ awk '$1="1."NR","$1,$2="2."NR","$2' nowcoder.txt | tr " " "\n" | sort -n | awk -F "," '{print $2}' | tr "\n" " " | awk -F" " '$5="\n"$5'
job c++ java php
salary 13 14 12

方法五:rs(拓展方法)

这个命令牛客没有哈,自己知道就行。

lucky@DESKTOP-VQ8KID4:~$ rs -Tzc' ' < nowcoder.txt
job     c++  java  php
salary  13   14    12

你可能感兴趣的:(Linux,bash,linux,rs,awk,xargs)