如何将项目序列分组为方括号
例如
项目清单
cat item.txt
sn01
sn02
sn03
sn05
sn07
sn08
期望的输出
sn[01-03,05,07-08]
答案 0 :(得分:1)
如果您的数据与显示的Input_file示例相同,那么以下内容可能对您有帮助。
awk 'FNR==1{line=$0} {sub(/[a-z]+/,"")} $0-val>1 && val1!=val{out=out?out "," val1"-"val:line"[" val1"-"val;val1=$0} $0-val>1 && val1==val{out=out?out "," val1:out "," val1;val1=$0} {if(FNR==1){sub(/[0-9]+/,"",line);val1=$0};val=$0}END{if(val1!=val){print out "," val1"-"val"]"} else {print out "," val"]"}}' Input_file
也添加非单一衬里形式的解决方案。
awk '
FNR==1{
line=$0
}
{
sub(/[a-z]+/,"")
}
$0-val>1 && val1!=val{
out=out?out "," val1"-"val:line"[" val1"-"val;
val1=$0
}
$0-val>1 && val1==val{
out=out?out "," val1:out "," val1;
val1=$0
}
{
if(FNR==1){
sub(/[0-9]+/,"",line);
val1=$0
};
val=$0
}
END{
if(val1!=val){
print out "," val1"-"val"]"
}
else{
print out "," val"]"
}
}
' Input_file
输出如下。
sn[01-03,05,07-08]
答案 1 :(得分:1)
“sn”在这里是静态的。它应该从输入文件中选择它。当我 给定的项目列表以“cn”开头。仍然选择“sn”
使用 var list = new int[] { 4,5,6};
var whereFunction = new Interpreter()
.SetVariable("mylist", list)
.Reference(typeof(ExtensionMethods));
whereFunction.ParseAsExpression<Func<Person, bool>>("(person.Age == 5 && person.Name.StartsWith(\"G\")) || person.Age == 3 && mylist.Exists(person.Id)", "person");
// Define this class somewhere
public static class ExtensionMethods
{
public static bool Exists<T>(this IEnumerable arr, T searchKey)
{
return ((IEnumerable<T>)arr).Contains(searchKey);
}
}
:
awk
$ cat infile
sn01
sn02
sn03
sn05
sn07
sn08
cn08
cn09
cn10
cn11
cn15
search='sn'
$ awk -v search='sn' 'function pr(){if(f && l)printf("%s%s",n?",":search"[",f==l?f:f"-"l)}$0!~"^"search{next}{t=$1;sub(/[^0-9]+/,"",t)}f==""{f=l=t;next}t==l+1{l=t;next}{pr();f=l=t;n++}END{pr(); print n?"]":"Nothing matched for keyword :"search}' infile
sn[01-03,05,07-08]
search='cn'
更好的可读性:
$ awk -v search='cn' 'function pr(){if(f && l)printf("%s%s",n?",":search"[",f==l?f:f"-"l)}$0!~"^"search{next}{t=$1;sub(/[^0-9]+/,"",t)}f==""{f=l=t;next}t==l+1{l=t;next}{pr();f=l=t;n++}END{pr(); print n?"]":"Nothing matched for keyword :"search}' infile
cn[08-11,15]
答案 2 :(得分:1)
一个简单的 awk 解决方案
我们的目标是为每个可能的范围设置LB
和UB
。
从LB
开始,common difference
为1的最后一个数字为UB
提供给我们。
如果差异大于1
则打印最后一个范围并再次设置LB
。
$ awk 'FNR==1{ $1=$1; prefix=substr($0,1,2);} {gsub(/[^0-9]/,"",$1); a[++i]=$1;} END{ printf prefix"["; LB=UB=prev=a[1]; for(i=1; i<=NR; i++){ if(int(a[i+1])==int(prev+1)) { UB=a[i+1]; prev=UB; } else { if(LB==UB) { printf LB"," } else {delim=(i==NR)? "]" :","; printf LB "-" UB delim; } prev=LB=UB=a[i+1]; }} }' file
sn[01-03,05,07-08]
gsub(/[^0-9]/,"",$1)
:这会将所有非数字字符设置为空。因此,$1
最终只有数字;
更好地理解它:
$ awk 'FNR==1{ $1=$1; prefix=substr($0,1,2); } {gsub(/[^0-9]/,"",$1); a[++i]=$1;}
END
{
printf prefix"["; LB=UB=prev=a[1];
for(i=1; i<=NR; i++)
{
if(int(a[i+1])==int(prev+1))
{
UB=a[i+1];
prev=UB; }
else
{
if(LB==UB)
{
printf LB","
}
else
{
delim=(i==NR)? "]" :",";
printf LB "-" UB delim;
}
prev=LB=UB=a[i+1];
}
}
}' file
答案 3 :(得分:0)
Awk 解决方案:
awk '{ v=substr($0,3) }NR==1{ pfx=substr($0,1,2); r=a=v; next }
{ diff=v-a; if(diff>1) { r=r ((a==last)? ",":"-"a",")v; last=v } a=v }
END{ if(diff==1) r=r"-"v; print pfx"["r"]" }' file
输出:
sn[01-03,05,07-08]