我有一个看起来像这样的CSV文件
AS2345,ASDF1232, Mr. Plain Example, 110 Binary ave.,Atlantis,RI,12345,(999)123-5555,1.56 AS2345,ASDF1232, Mrs. Plain Example, 1121110 Ternary st. 110 Binary ave..,Atlantis,RI,12345,(999)123-5555,1.56 AS2345,ASDF1232, Mr. Plain Example, 110 Binary ave.,Liberty City,RI,12345,(999)123-5555,1.56 AS2345,ASDF1232, Mr. Plain Example, 110 Ternary ave.,Some City,RI,12345,(999)123-5555,1.56
我需要按行长度(包括空格)对其进行排序。以下命令不会 包含空格,有没有办法修改它以便它对我有用?
cat $@ | awk '{ print length, $0 }' | sort -n | awk '{$1=""; print $0}'
答案 0 :(得分:183)
cat testfile | awk '{ print length, $0 }' | sort -n -s | cut -d" " -f2-
或者,对任何等长线进行原始(可能是无意的)子排序:
cat testfile | awk '{ print length, $0 }' | sort -n | cut -d" " -f2-
在这两种情况下,我们都通过远离awk来解决你所说的问题。
问题没有说明是否需要对匹配长度的行进行进一步排序。我假设这是不需要的,并建议使用-s
(--stable
)来防止这些行相互排序,并保持它们在输入中出现的相对顺序。
(那些想要更多控制对这些关系进行排序的人可能会考虑排序的--key
选项。)
值得注意的是:
之间的区别echo "hello awk world" | awk '{print}'
echo "hello awk world" | awk '{$1="hello"; print}'
他们分别屈服
hello awk world
hello awk world
relevant section of (gawk's) manual只提到了当你改变一个字段时,awk将重建整个$ 0(基于分隔符等)。我想这不是疯狂的行为。有这个:
“最后,有时候使用字段和OFS的当前值强制awk重建整个记录很方便。为此,请使用看似无害的任务:”
$1 = $1 # force record to be reconstituted
print $0 # or whatever else with $0
“这迫使awk重建记录。”
aa A line with MORE spaces
bb The very longest line in the file
ccb
9 dd equal len. Orig pos = 1
500 dd equal len. Orig pos = 2
ccz
cca
ee A line with some spaces
1 dd equal len. Orig pos = 3
ff
5 dd equal len. Orig pos = 4
g
答案 1 :(得分:18)
AWK solution from neillb非常棒,如果你真的想使用awk
并且它解释了为什么那里有麻烦,但如果你想要的是快速完成工作并且不在乎你是什么做到这一点,一个解决方案是使用Perl的sort()
函数和自定义caparison例程迭代输入行。这是一个班轮:
perl -e 'print sort { length($a) <=> length($b) } <>'
您可以将它放在您需要它的管道中,或者接收STDIN(来自cat
或shell重定向),或者只是将文件名作为另一个参数提供给perl并让它打开文件。
在我的情况下,我首先需要最长的行,所以我在比较中换了$a
和$b
。
答案 2 :(得分:13)
请尝试使用此命令:
awk '{print length, $0}' your-file | sort -n | cut -d " " -f2-
答案 3 :(得分:6)
基准测试结果
以下是基准测试的结果。
另外,我添加了另一个Perl解决方案:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="../../../../favicon.ico">
<title>Sticky Footer Navbar Template for Bootstrap</title>
<!-- Bootstrap core CSS -->
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="sticky-footer-navbar.css" rel="stylesheet">
<style>
html {
position: relative;
height: 100%;
}
body {
/* Margin bottom by footer height */
}
.footer {
position: absolute;
bottom: 0;
width: 100%;
/* Set the fixed height of the footer here */
background-color:#000;
text-align:center;
color:#fff;
}
.footer-bottom{
padding:3px 0;
position:absolute;
bottom:0;
background-color:green;
text-align:center;
width:100%;
}
</style>
</head>
<body class="page-body">
<!-- Fixed navbar -->
<!-- Fixed navbar -->
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
<a class="navbar-brand" href="#">Fixed navbar</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#">Disabled</a>
</li>
</ul>
<form class="form-inline mt-2 mt-md-0">
<input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
</nav>
<!--[ container ] -->
<div class="container">
content here
</div>
<!--[ footer ] -->
<div class="footer">
<p>Place sticky footer content here.</p>
</div>
<div class="footer-bottom">
<p>footer Bottom</p>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<script src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script>
<script>
function sizing(){
var completeFooter = $(".footer").height() + $(".footer-bottom").height();
$(".footer").css("height", completeFooter);
$(".page-body").css("margin-bottom", completeFooter);
}
$(document).ready(sizing);
$(window).resize(sizing);
</script>
</body>
</html>
实验使用:
进行结果:
答案 4 :(得分:5)
Pure Bash:
declare -a sorted
while read line; do
if [ -z "${sorted[${#line}]}" ] ; then # does line length already exist?
sorted[${#line}]="$line" # element for new length
else
sorted[${#line}]="${sorted[${#line}]}\n$line" # append to lines with equal length
fi
done < data.csv
for key in ${!sorted[*]}; do # iterate over existing indices
echo -e "${sorted[$key]}" # echo lines with equal length
done
答案 5 :(得分:3)
length()
函数包含空格。我会对您的管道进行微调(包括避免UUOC)。
awk '{ printf "%d:%s\n", length($0), $0;}' "$@" | sort -n | sed 's/^[0-9]*://'
sed
命令直接删除awk
命令添加的数字和冒号。或者,保持格式不受awk
:
awk '{ print length($0), $0;}' "$@" | sort -n | sed 's/^[0-9]* //'
答案 6 :(得分:2)
如果您的文件包含以数字开头的行,我发现这些解决方案无效,因为它们将与所有计算的行一起按数字排序。解决方案是给sort
-g
(通用数字排序)标志而不是-n
(数字排序):
awk '{ print length, $0 }' lines.txt | sort -g | cut -d" " -f2-
答案 7 :(得分:2)
答案 8 :(得分:2)
1)纯awk溶液。假设行长不能大于1024 然后
cat文件名| awk'BEGIN {min = 1024; s =“”;} {l = length($ 0);如果(l 2)假设所有行只有1个单词的一种内衬bash解决方案,但是对于所有行都具有相同单词数的任何情况,都可以重做: LINES = $(猫文件名); $ LINES中的k;做printf“ $ k”;回声$ k | wc -L;完成|排序-k2 |头-n 1 |切-d“” -f1
答案 9 :(得分:1)
这是一种按字节长度排序的多字节兼容方法。它要求:
wc -m
可供您使用(macOS有)。LC_ALL=UTF-8
。您可以在.bash_profile中设置它,或者只需在以下命令之前添加它。testfile
的字符编码与您的语言环境匹配(例如,UTF-8)。这是完整的命令:
cat testfile | awk '{l=$0; gsub(/\047/, "\047\"\047\"\047", l); cmd=sprintf("echo \047%s\047 | wc -m", l); cmd | getline c; close(cmd); sub(/ */, "", c); { print c, $0 }}' | sort -ns | cut -d" " -f2-
逐个部分解释:
l=$0; gsub(/\047/, "\047\"\047\"\047", l);
←awk变量l
中每行的副本,并且每'
双重转义,因此该行可以安全地回显为shell命令(\047
是八进制表示法中的单引号)。cmd=sprintf("echo \047%s\047 | wc -m", l);
←这是我们要执行的命令,它将转义的行回传到wc -m
。cmd | getline c;
←执行命令并复制返回到awk变量c
的字符计数值。close(cmd);
←关闭管道命令,以避免在一个进程中对打开文件的数量达到系统限制。sub(/ */, "", c);
←从wc
返回的字符数值中修剪空格。{ print c, $0 }
←打印行的字符计数值,空格和原始行。| sort -ns
←按行(-n
)对行(按前置字符计数值)进行排序,并维护稳定的排序顺序(-s
)。| cut -d" " -f2-
←删除前置字符计数值。它很慢(在快速的Macbook Pro上每秒只有160行),因为它必须为每一行执行一个子命令。
或者,只需使用gawk
(从版本3.1.5开始,gawk是多字节识别的),这将显着更快。执行所有转义和双引用以安全地通过来自awk的shell命令传递线路是很麻烦的,但这是我能找到的唯一方法,不需要安装其他软件(gawk默认情况下不可用)苹果系统)。
答案 10 :(得分:1)
使用Raku(以前称为Perl6)
~$ cat "BinaryAve.txt" | raku -e 'given lines() {.sort(*.chars).join("\n").say};'
AS2345,ASDF1232, Mr. Plain Example, 110 Binary ave.,Atlantis,RI,12345,(999)123-5555,1.56
AS2345,ASDF1232, Mr. Plain Example, 110 Ternary ave.,Some City,RI,12345,(999)123-5555,1.56
AS2345,ASDF1232, Mr. Plain Example, 110 Binary ave.,Liberty City,RI,12345,(999)123-5555,1.56
AS2345,ASDF1232, Mrs. Plain Example, 1121110 Ternary st. 110 Binary ave..,Atlantis,RI,12345,(999)123-5555,1.56
要反转排序,请在方法调用链的中间添加.reverse
,紧接在.sort()
之后。以下代码显示.chars
包含空格:
~$ cat "number_triangle.txt" | raku -e 'given lines() {.map(*.chars).say};'
(1 3 5 7 9 11 13 15 17 19 0)
~$ cat "number_triangle.txt"
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
1 2 3 4 5 6 7
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9 0
以下是使用Genbank的9.1MB txt文件对awk和Raku进行的时间比较:
~$ time cat "rat_whole_genome.txt" | raku -e 'given lines() {.sort(*.chars).join("\n").say};' > /dev/null
real 0m1.308s
user 0m1.213s
sys 0m0.173s
~$ #awk code from neillb
~$ time cat "rat_whole_genome.txt" | awk '{ print length, $0 }' | sort -n -s | cut -d" " -f2- > /dev/null
real 0m1.189s
user 0m1.170s
sys 0m0.050s
HTH。
答案 11 :(得分:0)
重温这个。这就是我的处理方式(计算 LINE 的长度并将其存储为 LEN,按 LEN 排序,仅保留 LINE):
cat test.csv | while read LINE; do LEN=$(echo ${LINE} | wc -c); echo ${LINE} ${LEN}; done | sort -k 2n | cut -d ' ' -f 1