根据最后一个点拆分并使用字符串的最后部分创建一个新列
split based on the last dot and create a new column with the last part of the string
我有一个包含 2 列的文件。第一列中有几个字符串 (ID),第二列中有多个值。在字符串中,有许多可以变化的点。我想根据最后一个点拆分这些字符串。我在论坛上找到了如何删除最后一个点之后的最后一个过去,但我不想删除它。我想用字符串的最后一部分创建一个新列,使用 bash 命令(例如 awk)
字符串示例:
5_8S_A.3-C_1.A 50
6_FS_B.L.3-O_1.A 20
H.YU-201.D 80
UI-LP.56.2011.A 10
输出示例:
5_8S_A.3-C_1 A 50
6_FS_B.L.3-O_1 A 20
H.YU-201 D 80
UI-LP.56.2011 A 10
我尝试使用以下命令解决它,但如果我在字符串中只有 1 个点,它就可以工作:
awk -F' ' '{{split(, arr, "."); print arr[1] "\t" arr[2] "\t" }}' file.txt
您可以使用这个 sed
:
sed -E 's/^([[:blank:]]*[^[:blank:]]+)\.([^[:blank:]]+)/ /' file
5_8S_A.3-C_1 A 50
6_FS_B.L.3-O_1 A 20
H.YU-201 D 80
UI-LP.56.2011 A 10
详情:
^
: 开始
([[:blank:]]*[^[:blank:]]+)
:捕获第 2 组以匹配 0 个或多个白色space 后跟 1+ 个非白色space 字符。
\.
:匹配一个点。由于此正则表达式模式是 greedy 它将匹配到最后一个点
([^[:blank:]]+)
:捕获第 2 组以匹配 1+ 个非白色space 字符
:替换以在捕获值 #1 和捕获值 #2 之间放置一个 space
假设:
- 每行由两个(白色)space 分隔字段组成
- 第一个字段至少包含一个句点(
.
)
坚持 OP 的愿望 (?) 使用 awk
:
awk '
{ n=split(,arr,".") # split first field on period (".")
pfx=""
for (i=1;i<n;i++) { # print all but the nth array entry
printf "%s%s",pfx,arr[i]
pfx="."}
print "\t" arr[n] "\t" } # print last array entry and last field of line
' file.txt
删除评论并减少到一行:
awk '{n=split(,arr,"."); pfx=""; for (i=1;i<n;i++) {printf "%s%s",pfx,arr[i]; pfx="."}; print "\t" arr[n] "\t" }' file.txt
这会生成:
5_8S_A.3-C_1 A 50
6_FS_B.L.3-O_1 A 20
H.YU-201 D 80
UI-LP.56.2011 A 10
根据您展示的示例,这里是 rev
+ awk
解决方案的另一种变体。
rev Input_file | awk '{sub(/\./,OFS)} 1' | rev
解释: 简单的解释就是,使用rev
倒序打印(从最后一个字符到第一个字符)对于每一行,然后将其输出作为标准输入发送到 awk
程序,其中用空格替换第一个点(仅根据 OP 显示的样本是最后一个点)并打印所有行。然后再次将此输出作为标准输入发送到 rev
以按正确顺序打印输出(以消除此处 1st rev 命令的影响)。
$ sed 's/\.\([^.]*$\)/\t/' file
5_8S_A.3-C_1 A 50
6_FS_B.L.3-O_1 A 20
H.YU-201 D 80
UI-LP.56.2011 A 10
我有一个包含 2 列的文件。第一列中有几个字符串 (ID),第二列中有多个值。在字符串中,有许多可以变化的点。我想根据最后一个点拆分这些字符串。我在论坛上找到了如何删除最后一个点之后的最后一个过去,但我不想删除它。我想用字符串的最后一部分创建一个新列,使用 bash 命令(例如 awk)
字符串示例:
5_8S_A.3-C_1.A 50
6_FS_B.L.3-O_1.A 20
H.YU-201.D 80
UI-LP.56.2011.A 10
输出示例:
5_8S_A.3-C_1 A 50
6_FS_B.L.3-O_1 A 20
H.YU-201 D 80
UI-LP.56.2011 A 10
我尝试使用以下命令解决它,但如果我在字符串中只有 1 个点,它就可以工作:
awk -F' ' '{{split(, arr, "."); print arr[1] "\t" arr[2] "\t" }}' file.txt
您可以使用这个 sed
:
sed -E 's/^([[:blank:]]*[^[:blank:]]+)\.([^[:blank:]]+)/ /' file
5_8S_A.3-C_1 A 50
6_FS_B.L.3-O_1 A 20
H.YU-201 D 80
UI-LP.56.2011 A 10
详情:
^
: 开始([[:blank:]]*[^[:blank:]]+)
:捕获第 2 组以匹配 0 个或多个白色space 后跟 1+ 个非白色space 字符。\.
:匹配一个点。由于此正则表达式模式是 greedy 它将匹配到最后一个点([^[:blank:]]+)
:捕获第 2 组以匹配 1+ 个非白色space 字符
假设:
- 每行由两个(白色)space 分隔字段组成
- 第一个字段至少包含一个句点(
.
)
坚持 OP 的愿望 (?) 使用 awk
:
awk '
{ n=split(,arr,".") # split first field on period (".")
pfx=""
for (i=1;i<n;i++) { # print all but the nth array entry
printf "%s%s",pfx,arr[i]
pfx="."}
print "\t" arr[n] "\t" } # print last array entry and last field of line
' file.txt
删除评论并减少到一行:
awk '{n=split(,arr,"."); pfx=""; for (i=1;i<n;i++) {printf "%s%s",pfx,arr[i]; pfx="."}; print "\t" arr[n] "\t" }' file.txt
这会生成:
5_8S_A.3-C_1 A 50
6_FS_B.L.3-O_1 A 20
H.YU-201 D 80
UI-LP.56.2011 A 10
根据您展示的示例,这里是 rev
+ awk
解决方案的另一种变体。
rev Input_file | awk '{sub(/\./,OFS)} 1' | rev
解释: 简单的解释就是,使用rev
倒序打印(从最后一个字符到第一个字符)对于每一行,然后将其输出作为标准输入发送到 awk
程序,其中用空格替换第一个点(仅根据 OP 显示的样本是最后一个点)并打印所有行。然后再次将此输出作为标准输入发送到 rev
以按正确顺序打印输出(以消除此处 1st rev 命令的影响)。
$ sed 's/\.\([^.]*$\)/\t/' file
5_8S_A.3-C_1 A 50
6_FS_B.L.3-O_1 A 20
H.YU-201 D 80
UI-LP.56.2011 A 10