我有一个包含列表和子列表的文件,我想使用命令行工具提取最长的子列表。
文件示例:
* Item1
** SubItem1
** ...
** SubItemN
* Item2
** SubItem1
** ...
** SubItemN
* ...
** ...
* ItemN
** SubItem1
** ...
** SubItemN
我想知道这是否可以轻松完成,否则我将编写一个 Perl 脚本。
Perl 单行:
perl -00 -ne '$n=tr/\n/\n/; if ($n>$m) {$m=$n; $max=$_}; END {print $max}' file
只需使用 bash:
max=0
while read bullet thingy; do
case $bullet in
"*") item=$thingy; count=0 ;;
"**") ((count++)) ;;
"") (( count > max )) && { max_item=$item; max=$count; } ;;
esac
done < <(cat file; echo)
echo $max_item $max
<(cat file; echo)
部分是保证文件最后一行后面有一个空行,这样最后的sublist group可以和max进行比较
那只会保持计数。要将项目保存在最大的子列表中:
max=0
while read bullet thingy; do
case $bullet in
"*") item=$thingy; unset sublist; sublist=() ;;
"**") sublist+=($thingy) ;;
"") if (( ${#sublist[@]} > max )); then
max=${#sublist[@]}
max_item=$item
max_sublist=("${sublist[@]}")
fi
;;
esac
done < <(cat file; echo)
printf "%s\n" "$max_item" "${#max_sublist[@]}" "${max_sublist[@]}"
如果使用 sudo_O 的示例,则输出
letters
6
a
b
b
d
e
f
$ cat file
* letters
** a
** b
** b
** d
** e
** f
* colors
** red
** green
** blue
* numbers
** 1
** 2
** 3
** 4
** 5
tac
通过使用和使用反转文件来显示每个子列表的长度awk
:
$ tac file | awk '/^\*\*/{c++}/^\*[^*]/{print c,$2;c=0}'
5 numbers
3 colors
6 letters
仅打印最大子列表的长度:
$ tac file | awk '/^\*\*/{c++}/^\*[^*]/{if(c>m){m=c;l=$2}c=0}END{print m,l}'
6 letters
cat file.txt | grep -nE "^\*[^\*].*" | cut -d ":" -f 1,1 | tee tmp | awk 'NR==1{s=$1;next} {print $1-s;s=$1}' > tmp2
echo 0 >> tmp2
res=`paste tmp tmp2 | sort -nrk 2,2 | head -n 1`
line=`echo "$res" | cut -f 1,1`
ln=`echo "$res" | cut -f 2,2`
cat file.txt | tail -n +$line | head -n $ln
rm tmp tmp2
肯定有一个更短的解决方案:)