![](/img/trans.png)
[英]Return the number of lines required for paragraphs of text for a given width in Bash
[英]Sort text columns by number of lines in bash
假設一個包含x個字符串列的文本文件。
$cat file # where x=3
foo foo foo
bar bar bar
baz baz
qux
在bash中是否有一種方法可以按照它們包含的數字文本字符串(即填充的行)對這些列進行排序,同時保持每列中行的內部順序?
$sought_command file
foo foo foo
bar bar bar
baz baz
qux
基本上,具有最多行數的列是第一個,具有第二多行數的列是第二個,等等。
(這個任務很容易通過R
實現,但我想知道通過bash的解決方案。)
編輯1 :
以下是一些其他詳細信息:每列包含至少一個文本字符串(即一個填充行)。 文本字符串可以構成任何字母數字組合並且具有任何長度(但顯然不包含空格)。 輸出列不得插入空行。 列分隔符沒有先驗限制,只要它在整個表中保持一致即可。
此任務所需的只是按原樣移動列,以便按列長度排序。 (我知道在bash中實現它聽起來比實際更容易。)
使用GNU awk for sorted_in並假設您的列是以制表符分隔的:
$ cat tst.awk
BEGIN{ FS=OFS="\t" }
{
for (i=1; i<=NF; i++) {
if ($i ~ /[^[:space:]]/) {
cell[NR,i] = $i
cnt[i]++
}
}
next
}
END {
PROCINFO["sorted_in"] = "@val_num_desc"
for (row=1; row<=NR; row++) {
c=0
for (col in cnt) {
printf "%s%s", (c++?OFS:""), cell[row,col]
}
print ""
}
}
$ awk -f tst.awk file
foo foo foo
bar bar bar
baz baz
qux
首先創建一個名為transpose的函數:
transpose() {
awk -v FPAT='[^[:blank:]]+|[ \t]{3,}' '{
for (i=1; i<=NF; i++)
a[i,NR]=$i
max=(max<NF?NF:max)
}
END {for (i=1; i<=max; i++)
for (j=1; j<=NR; j++)
printf "%s%s", a[i,j], (j==NR?ORS:OFS)
}'
}
然后用它作為:
transpose < file | awk '{print NF "\t" $0}' | sort -k1nr | cut -f2- | transpose
foo foo foo
bar bar bar
baz baz
qux
步驟是:
transpose
函數將列轉換為行 awk
在每行的開頭添加字段數 sort
cut
來擺脫第一列 transpose
以將列轉置為行以獲得原始順序 PS:由於使用FPAT
我們需要gnu-awk。
使用unix工具集
$ tr '\t' '\n' <file |
pr -4ts |
awk '{print gsub(/-/,"-") "\t" $0}' |
sort -k1n |
cut -f2- |
tr '\t' '\n' |
pr -3ts
foo foo foo
bar bar bar
baz baz -
qux - -
假設列是制表符分隔的,缺少的值用“ - ”表示。 幻數4和3分別是行數和列數。
用它作為輸入文件
$ cat file
foo foo foo
bar bar bar
- baz baz
- qux -
sed -e 's/^ *//' columns.txt
# =>
# foo foo foo
# bar bar bar
# baz baz
# qux
我整個星期都會在這里! :d
更嚴重的是,您可能希望使用bash轉置列 ,使用awk
或rs
。 這樣可以更輕松地對列(現在是行)進行排序,並再次將它們轉置回來。 但是,多個空格可能會給awk
帶來awk
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.