linux中shell脚本——shell数组、正则表达式及文件三剑客之AWK

目录

一.shell数组

1.1.数组分类

1.2.定义数组方法

二.正则表达式

2.1.元字符

2.2.表示次数

2.3.位置锚定

2.4.分组

2.5.扩展正则表达式

三.文本三剑客之AWK

3.1.awk介绍及使用格式

3.2.处理动作

3.3.awk选项

3.4.awk处理模式

2.5.awk常见的内置变量 

2.6.if条件判断


一.shell数组

1.1.数组分类

①关联数组:必须声明才可以使用,命令:delare  -A   数组名  

②普通数组:利用数字下标节约变量,可以不声明也可以声明,命令:delare -a  数组名

delare  -a命令也可查看有哪些普通数组

1.2.定义数组方法

(1)普通数组

数组名=(vlaue0  vlaue1  vlaue2  ...)[root@zrsb  ~]#a=(10 20 30)    #定义数组a,值为10 20 30 
[root@zrsb  ~]#echo ${a[0]}    #输出数组a下标为0的元素
10
[root@zrsb  ~]#echo ${a[@]}    #输出数组a中所有的元素
10 20 30
[root@zrsb  ~]#echo ${a[*]}    #输出数组a中所有的元素
10 20 30
[root@zrsb  ~]#echo ${#a[@]}   #输出数组a中元素的个数
3
[root@zrsb  ~]#echo ${!a[@]}   #输出数组a中元素的下标
0 1 2
[root@zrsb  ~]#a[0]=100        #重新定义数组a下标为0的元素为100
[root@zrsb  ~]#echo ${a[0]}    #输出数组a中下标为0的元素
100

(2)关联数组定义

delare -A  数组名   #声明数组
数组名[下标]=元素    #定义关联数组[root@zrsb  ~]#declare -A f       #声明关联数组f
[root@zrsb  ~]#f[name]=pc1        #定义关联数组f下标name的元素为pc1
[root@zrsb  ~]#f[ip]=10.0.0.0     #定义关联数组f下标ip的元素为10.0.0.0
[root@zrsb  ~]#echo ${f[@]}       #输出关联数组f的所有元素值
zrsb 10.0.0.0
[root@zrsb  ~]#echo ${!f[@]}      #输出关联数组f中元素的所有下标
name ip

二.正则表达式

注意事项:使用正则表达式必须加引号。

2.1.元字符

(1).:在正则表达式中.表示任意单个字符

[root@zrsb  data]#grep   -o r.t /etc/passwd #过滤passwd文件中开头为r中间任意单个字符结尾为t的内容
rat
rat
rat
[root@zrsb  data]#grep   -o r..t /etc/passwd #过滤passwd文件中开头为r中间任意2个字符结尾为t的内容
root
root
root
root
r/ft
[root@zrsb  data]#grep   -o r...t /etc/passwd #过滤passwd文件中开头为r中间任意3个字符结尾为t的内容
rtkit

(2)[  ]:在正则表达式中[ ]表示匹配[ ]中任意一个字符

[root@zrsb data]#touch {a..c}.txt #创建a-c.txt文件夹
[root@zrsb data]#ls               #显示文件夹内容
a.txt  b.txt  c.txt 
[root@zrsb data]#ls |grep '[a-z].txt' #使用grep过滤ls中有任意一个a-z字母.txt的文件
a.txt
b.txt
c.txt

(3)[^]:在正则表达式中表示匹配[ ]中外的任意单个字符。 

[root@zrsb  data]#touch {a..c}.txt        #创建a-c.txt文件
[root@zrsb  data]#touch {0..2}.txt        #创建0-2.txt文件
[root@zrsb  data]#ls                      #显示文件
0.txt  1.txt  2.txt  a.txt  b.txt  c.txt
[root@zrsb  data]#ls |grep '[^0-9].txt'   #过滤ls显示文件中除去0-9任意字符.txt文件
a.txt
b.txt
c.txt
[root@zrsb  data]#ls |grep '[^a-z].txt'   #过滤ls显示文件中除去a-z任意字符.txt文件
0.txt
1.txt
2.txt

[:alnum:] 字母和数字
[:alpha:] 代表任何英文大小写字符,亦即 A-Z, a-z
[:lower:] 小写字母,示例:[[:lower:]],相当于[a-z]
[:upper:] 大写字母
[:blank:] 空白字符(空格和制表符)
[:space:] 包括空格、制表符(水平和垂直)、换行符、回车符等各种类型的空白,比[:blank:]包含的范围广
[:cntrl:] 不可打印的控制字符(退格、删除、警铃...)
[:digit:] 十进制数字
[:xdigit:]十六进制数字
[:graph:] 可打印的非空白字符
[:print:] 可打印字符
[:punct:] 标点符号

[root@zrsb  data]#echo AB12ab | grep -o '[[:alpha:]]'  #过滤输出内容的字母
A
B
a
b
[root@zrsb  data]#echo AB12ab | grep -o '[[:alnum:]]'  #过滤输出内容的字母和数字
A
B
1
2
a
b
[root@zrsb  data]#echo AB12ab | grep -o '[[:lower:]]'  #过滤输出内容的小写字母
a
b
[root@zrsb  data]#echo AB12ab | grep -o '[[:upper:]]'  #过滤输出内容的大写字母
A
B

2.2.表示次数

(1)*:表示匹配前面字符任意次,包括0次。

[root@zrsb  ~]#echo  ac |grep 'ab*c'  #ab之间不输入b可匹配
ac
[root@zrsb  ~]#echo  abc |grep 'ab*c' #ab之间输入1个b可匹配
abc
[root@zrsb  ~]#echo  abbc |grep 'ab*c'#ab之间输入2个b可匹配
abbc

(2).*:表示匹配前面字符任意次,不包括0次。

[root@zrsb  ~]#echo ac |grep 'ab.*c'  #ac之间不输入b匹配不到
[root@zrsb  ~]#echo abc |grep 'ab.*c' #ac之间输入1个b可以匹配
abc
[root@zrsb  ~]#echo abbc |grep 'ab.*c' #ac直接输入2个b可以匹配
abbc

(3)\?:表示匹配前面的字符1次或0次,即可有可无。

[root@zrsb  ~]#echo ac | grep 'ab\?c'    #ac之间不输入b可以匹配
ac
[root@zrsb  ~]#echo abc | grep 'ab\?c'   #ac之间输入1个b可以匹配
abc
[root@zrsb  ~]#echo abbc | grep 'ab\?c'  #ac之间输入2个b匹配不到 

(4)\+:表示匹配前面的字符最少1次。

[root@zrsb  ~]#echo ac | grep 'ab\+c'  #ac之间不输入b匹配不到
[root@zrsb  ~]#echo abc | grep 'ab\+c' #ac之间输入1个b可以匹配
abc
[root@zrsb  ~]#echo abbbbc | grep 'ab\+c' #ac之间输入多个b可以匹配
abbbbc

(5)\{n\}:表示匹配前面的字符n次。

[root@zrsb  ~]#echo abbbc |grep 'ab\{3\}c'  #输出abbbc匹配ac之间b字符出现3次可以匹配
abbbc
[root@zrsb  ~]#echo abbbbc |grep 'ab\{3\}c' #输出abbbbc匹配ac之间b字符出现3次匹配不到

(6)\{m,n\}:表示匹配前面的字符最少m次最多n次。

[root@zrsb ~]#echo abc |grep 'ab\{1,3\}c'  #输出abc匹配ac之间b出现最少1次最多3次可以匹配
abc
[root@zrsb  ~]#echo abbc |grep 'ab\{1,3\}c' #输出abbc匹配ac之间b出现最少1次最多3次可以匹配
abbc
[root@zrsb  ~]#echo abbbc |grep 'ab\{1,3\}c'#输出abbbc匹配ac之间b出现最少1次最多3次可以匹配
abbbc
[root@zrsb  ~]#echo abbbbc |grep 'ab\{1,3\}c'#输出abbbbc匹配ac之间b出现最少1次最多3次匹配不到

(7)\{m,\}:表示匹配前面的字符最少m次。

(8)\{,n\}:表示匹配前面的字符最多n次。

2.3.位置锚定

(1)^表示以什么字符开头的行。

(2)$表示以什么字符为结尾的行。

(3)^PATTERN$ 表示用于模式匹配整行 (单独一行  只有PATTERN字符)。

(4)^$ 表示空行。

(5)\< 或 \b        #词首锚定,用于单词模式的左侧(连续的数字,字母,下划线都算单词内部)。

(6)\> 或 \b       #词尾锚定,用于单词模式的右侧。

(7)\<PATTERN\>    #匹配整个单词。

[root@zrsb ~]#cat a.txt                #查看a.txt内容 
root
abc   abd  abf abe 
asfase
asdfasfewe
[root@zrsb~]#cat a.txt |grep '^a'     #查看a.txt内容过滤以a开头的行
abc   abd  abf abe 
asfase
asdfasfewe
[root@zrsb ~]#cat a.txt |grep 'e$'     #查看a.txt内容过滤以e为结尾的行
asfase
asdfasfewe
[root@zrsb ~]#cat a.txt |grep '^root$' #查看a.txt内容过滤只有root字符的行
root
[root@zrsb ~]#cat a.txt |grep '\ba'    #查看a.txt过滤以a开头的词
abc   abd  abf abe 
asfase
asdfasfewe
[root@zrsb ~]#cat a.txt |grep 'e\b'    #查看a.txt过滤以e为结尾的词
abc   abd  abf abe 
asfase
asdfasfewe
[root@zrsb ~]#cat a.txt |grep -o '\babc\b' #查看a.txt过滤次abc
abc 

2.4.分组

()将多个字符捆绑在一起当做一个整体处理

[root@zrsb ~]#echo abcccc |grep "abc\{4\}"  #匹配输出内容c出现4次
abcccc
[root@zrsb  ~]#echo abcccc |grep "\(abc\)\{4\}" #abc字符加()分组匹配输出内容abc出现4次,无abc出现4次匹配不到
[root@zrsb  ~]#echo abcabcabcabc |grep "\(abc\)\{4\}"  #abc字符加()分组匹配输出内容abc出现4次匹配成功
abcabcabcabc

2.5.扩展正则表达式

(1)使用方法

grep  -E选项加正则表达式内容,与正常正则表达式区别在于不用在匹配时添加 \

(2)表示次数

*   匹配前面字符任意次
? 0或1次
+ 1次或多次
{n} 匹配n次
{m,n} 至少m,至多n次
{,n}  #匹配前面的字符至多n次,<=n,n可以为0
{n,} #匹配前面的字符至少n次,<=n,n可以为0

(3)表示分组

() 分组

三.文本三剑客之AWK

3.1.awk介绍及使用格式

awk为流编辑器,即读取文件一行处理一行。不同于vi编辑器等是将文件整个缓存在内容中处理。

awk  [选项]   '处理模式{处理动作}'

'{ }'为固定格式

举例:取出sda硬盘的容量
[root@zrsb data]#lsblk 
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0   60G  0 disk 
├─sda1            8:1    0    2G  0 part /boot
└─sda2            8:2    0   54G  0 part ├─centos-root 253:0    0   50G  0 lvm  /└─centos-swap 253:1    0    4G  0 lvm  [SWAP]
sdb               8:16   0   20G  0 disk 
sdc               8:32   0   20G  0 disk 
sdd               8:48   0   20G  0 disk 
sr0              11:0    1  4.2G  0 rom  
[root@zrsb data]#lsblk  |grep -w sda       #通过过滤sda字符将sda此行过滤出
sda               8:0    0   60G  0 disk 
[root@zrsb data]#lsblk  |grep -w sda | awk '{print $4}' #使用awk不指定分隔符 打印出第4列
60G

3.2.处理动作

(1)基本格式:awk  [选项]   '处理模式{处理动作}'

(2)print动作:打印,打印'{print $1}'即为打印第一列,'{print $n}'即打印为第n列,'{print $n,$m}'即为打印第n列和第m列。

(3)print打印顺序:'BEGIN{print "1"} END {print  "2"}  {print "3"} ',首先打印BEGIN后的print 1,然后打印print 3  最后打印END后的print 2,BEGIN表示第一个打印,END表示最后打印

举例1:
[root@zrsb data]#cat test.txt           #创建文件
1     2    3     4      5      6  7 8  @test.txt 文件内容
[root@zrsb data]#awk '{print $1}' test.txt  #使用awk处理文件test.txt打印第1列
1
[root@zrsb data]#awk '{print $5}' test.txt  #使用awk处理文件test.txt打印第5列
5
[root@zrsb data]#awk '{print $1,$5}' test.txt  #使用awk处理文件test.txt打印第1列和第5列
1 5举例2:
[root@zrsb data]#  awk 'BEGIN{print "1"} END{print "$2"} {print "3"}' test.txt
1
3
2

3.3.awk选项

①基本格式:awk  [选项]   '处理模式{处理动作}'

②选项若不写默认为以空格为分隔符处理,且会将空格自动压缩。

③-F 选项 指定分隔符,即指定以什么为分隔符处理内容

举例:
[root@zrsb data]#cat test.txt         #编辑test.txt内容
one    two   three
root:lisi:zhangsan
[root@zrsb data]#awk '{print $2}' test.txt  #默认过滤test内容以空格为分隔符打印出第2列为two
two
[root@zrsb data]#awk -F : '{print $2}' test.txt #使用-F选项指定以:为分隔符打印出第2列为lisilisi

3.4.awk处理模式

①基本格式:awk  [选项]   '处理模式{处理动作}'

②处理模式为空表示无其他额外条件。

③正则表达式匹配模式

正则匹配:与正则表达式配合使用。

举例:
[root@zrsb data]#cat test.txt      #创建test.txt
root 1   abc  2    3     4      5      6  7 8
abcdsadfasdf root[root@zrsb data]#awk   '/^root/{print $2}' test.txt #使用awk配合正则表达式打印出test.txt文件中以root为开头的行的第二列,注意处理模式在固定格式'{}'的单引号中 
1                                 #匹配出的内容[root@zrsb data]#awk   '/^root/,/root$/{print $2}' test.txt  #使用awk配合正则表达式打印出test.txt文件中以root为开头的且以root结尾的第二列,注意处理模式在固定格式'{}'的单引号中
1root                               #匹配出的内容

2.5.awk常见的内置变量 

比较操作符:==, !=, >, >=, <, <=

逻辑操作符:&&与 并且的关系,||或 或者关系,!非 取反关系

(1)FS :指定每行文本的字段分隔符,缺省为空格或制表符(tab)。与 “-F”作用相同 -v "FS=:"

[root@zrsb data]#cat a.txt 
a:b:c
[root@zrsb data]#awk -v "FS=:" '{print $2}' a.txt  使用FS变量指定:为分隔符打印a.txt文件的第二列
b

(2)OFS:输出时的分隔符

[root@zrsb data]#cat a.txt 
a:b:c
[root@zrsb data]#awk -v "FS=:"  -v OFS="==" '{print $1OFS$3}' a.txt  使用FS变量指定:为分隔符且指定输出分隔符OFS为==,打印a.txt文件的第1列和第3列
a==b

(3)NF:当前处理的行的字段个数即处理行有多少列,默认按空格分列,可指定

awk -F : '{print NF}'  /etc/passwd  |head -n 1
#指定:为分隔符打印出文件/etc/passwd第一行有多少个字段,即多少列awk -F : '{print $(NF-1)}'  /etc/passwd |head -n 1 
#指定:为分隔符打印出文件/etc/passwd第一行的倒数第二个字段,即倒数第二列
/root

(4)NR:当前处理的行的行号(序数)

awk -F :   'NR==1{print $1}'  /etc/passwd              #指定:为分隔符打印出/etc/passwd文件第一行的第一个变量,注意模式要写在'模式{}'位置awk -F :   'NR>=1 && NR<=3{PRINT $1}' /etc/passwd      #指定:为分隔符打印出/etc/passwd文件大于等于第一行且小于等于第三行的第三个变量

(5)$0:当前处理的行的整行内容

awk -F : 'NR==1{print $0}' /etc/passwd
#指定:为分隔符打印出文件/etc/passwd第一行的所有内容awk -F : 'NR>=1 && NR<=3{print $0}' /etc/passwd
#指定:为分隔符打印出文件/etc/passwd大于等于第一行且小于等于第三行的所有内容

(6)$n:当前处理行的第n个字段(第n列)

(7)FILENAME:被处理的文件名

(8)RS:行分隔符。awk从文件上读取资料时,将根据RS的定义就把资料切割成许多条记录,而awk一次仅读入一条记录进行处理。预设值是\n

2.6.if条件判断

if语句:awk的if语句也分为单分支、双分支和多分支
单分支为if(){}
双分支为if(){}else{}
多分支为if(){}else if(){}else{}
awk -F : '{if($3>1000)print $1,$3}' /etc/passwd
#指定:为分隔符过滤passwd文件第三列如果大于1000则大于出第一列和第三列

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/46450.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pytorch内存泄漏

问题描述&#xff1a; 内存泄漏积累过多最终会导致内存溢出&#xff0c;当内存占用过大&#xff0c;进程会被killed掉。 解决过程&#xff1a; 在代码的运行阶段输出内存占用量&#xff0c;观察在哪一块存在内存剧烈增加或者显存异常变化的情况。但是在这个过程中要分级确认…

基于Jenkins构建生产CICD环境(上篇)

目录 环境概述 Jenkins简介 持续集成 持续集成的效益 持续集成的作用 持续集成的特点 持续交付 持续部署 Maven 介绍 安装配置Jenkins Jenkins配置 1、修改jenkins初始密码 2、安装 Jenkins 必要插件 环境概述 随着软件开发需求及复杂度的不断提高&#xff0c;团队…

怎样通过本地电脑搭建SFTP服务器,并实现公网访问?

本地电脑搭建SFTP服务器&#xff0c;并实现公网访问 文章目录 本地电脑搭建SFTP服务器&#xff0c;并实现公网访问1. 搭建SFTP服务器1.1 下载 freesshd 服务器软件1.3 启动SFTP服务1.4 添加用户1.5 保存所有配置 2. 安装SFTP客户端FileZilla测试2.1 配置一个本地SFTP站点2.2 内…

appium2 安装 和出现问题解决

1.安装环境 A macOS, Linux, or Windows operating systemNode.js version in the SemVer range ^14.17.0 || ^16.13.0 || >=18.0.0NPM version >= 8 (NPM is usually bundled with Node.js, but can be upgraded independently) 1.1只要安装nodejs最新版就好了 1.2安…

el-table分页后序号连续的两种方法

实现效果&#xff1a; 第一页排序到10&#xff0c;第二页的排序应从11开始 实现方法一&#xff1a; 在el-table的序号列中使用template定义 <el-table><el-table-columnmin-width"10%"label"序号"><template slot-scope"scope"…

网络协议的定义、组成和重要性?

什么是网络协议&#xff1f; 网络协议是在计算机网络中&#xff0c;用于规定通信实体之间进行数据传输和通信的规则集合。网络协议涵盖了各种通信细节&#xff0c;包括数据包格式、错误处理、数据传输速率等&#xff0c;是用于分组交换数据网络的一种协议&#xff0c;其任务仅…

二、SQL,如何实现表的创建和查询

1、新建表格&#xff08;在当前数据库中新建一个表格&#xff09;&#xff1a; &#xff08;1&#xff09;基础语法&#xff1a; create table [表名]( [字段:列标签] [该列数据类型] comment [字段注释], [字段:列标签] [该列数据类型] comment [字段注释], ……&#xff0c…

SaaS ERP系统:中小企业走向成功的“秘密武器”

**ERP系统**开发已成为企业以最小的复杂性高效运营的必要需求。企业资源规划是业务流程管理战略不可或缺的一部分&#xff0c;因此&#xff0c;要想在当今动荡的市场中保持竞争力&#xff0c;拥有合适的ERP解决方案至关重要。 尽管如此&#xff0c;由于显而易见的原因&#xf…

玩转单元测试之gtest

引言 程序开发的时候&#xff0c;往往需要编写一些测试样例来完成功能测试&#xff0c;以保证自己的代码在功能上符合预期&#xff0c;能考虑到一些异常边界问题等等。 gtest快速入门 1.引入gtest # 使用的是1.10版本&#xff0c;其他版本可根据需要选择 git clone -b v1.1…

自动驾驶——车辆动力学模型

/*lat_controller.cpp*/ namespace apollo { namespace control {using apollo::common::ErrorCode;//故障码 using apollo::common::Status;//状态码 using apollo::common::TrajectoryPoint;//轨迹点 using apollo::common::VehicleStateProvider;//车辆状态信息 using Matri…

皮爷咖啡基于亚马逊云科技的数据架构,加速数据治理进程

皮爷咖啡&#xff08;Peet’s Coffee&#xff09;是美国精品咖啡品牌&#xff0c;于2017年进入中国&#xff0c;为中国消费者带来传统经典咖啡饮品&#xff0c;并特别呈现更加丰富的品质咖啡饮品体验。通过深入应用亚马逊云科技云原生数据库产品Amazon Redshift以及Amazon DMS等…

新研究:Gartner 公有云成本管理框架

2023年6月28日&#xff0c;Gartner 出版了名为《Beyond FinOps: the Gartner Framework for Public Cloud Financial Management》的公有云成本管理框架&#xff0c;旨在帮助企业/组织应对公有云支出的挑战&#xff0c;同时抓住新机遇&#xff0c;推动更有效的 IT 使用。新框架…

Practices11|41. 缺失的第一个正数(数组)、73. 矩阵置零(矩阵)

41. 缺失的第一个正数(数组) 1.题目&#xff1a; 给你一个未排序的整数数组 nums &#xff0c;请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,0] 输出&#xf…

web文件上传

文件上传指的是&#xff0c;将本地的图片、视频、音频上传到服务器&#xff0c;提供给其他用户浏览和下载的过程 前端需求 想要进行文件上传对于web前端来说有三个重要要素 1.<input type"file" name"image"> 提供这样的file文件上传格式 2. metho…

无代码集成飞书连接更多应用

场景描述&#xff1a; 基于飞书开放平台能力&#xff0c;无代码集成飞书连接更多应用&#xff0c;打通数据孤岛。通过Aboter可轻松搭建业务自动化流程&#xff0c;实现多个应用之间的数据连接。 支持包括飞书事件监听和接口调用的能力&#xff1a; 事件监听&#xff1a; 用…

神经网络基础-神经网络补充概念-54-softmax回归

概念 Softmax回归&#xff08;Softmax Regression&#xff09;是一种用于多分类任务的机器学习算法&#xff0c;特别是在神经网络中常用于输出层来进行分类。它是Logistic回归在多分类问题上的推广。 原理 Softmax回归的主要思想是将原始的线性分数&#xff08;得分&#xf…

SOPC之NIOS Ⅱ实现电机转速PID控制

通过FPGA开发板上的NIOS Ⅱ搭建电机控制的硬件平台&#xff0c;包括电机正反转、编码器的读取&#xff0c;再通过软件部分实现PID算法对电机速度进行控制&#xff0c;使其能够渐近设定的编码器目标值。 一、PID算法 PID算法&#xff08;Proportional-Integral-Derivative Algo…

Yalmip入门教程(5)-约束条件操作的相关函数

博客中所有内容均来源于自己学习过程中积累的经验以及对yalmip官方文档的翻译&#xff1a;https://yalmip.github.io/tutorials/ 这篇博客将详细介绍yalmip工具箱中约束条件操作相关函数的用法。 1.约束条件操作的相关函数 1.1 boundingbox函数 boundingbox函数用于求出一组约…

opencv 进阶13-Fisherfaces 人脸识别-函数cv2.face.FisherFaceRecognizer_create()

Fisherfaces 人脸识别 PCA 方法是 EigenFaces 方法的核心&#xff0c;它找到了最大化数据总方差特征的线性组合。不可否认&#xff0c;EigenFaces 是一种非常有效的方法&#xff0c;但是它的缺点在于在操作过程中会损失许多特征信息。 因此&#xff0c;在一些情况下&#xff0c…

PSP - 开源可训练的蛋白质结构预测框架 OpenFold 的环境配置

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132334671 Paper: OpenFold: Retraining AlphaFold2 yields new insights into its learning mechanisms and capacity for generalization Open…