在 Raku 中,給定的字串將被分成其單獨的字符。每個大寫字母的字符都用尖括號括起來,而每個其他字符都用單引號括起來。生成的字串將連接在一起,用空格分隔。
例子 …
- 如果給定的字串(沒有它的分隔引號)是
aSbTc,那么結果字串將是'a' <S> 'b' <T> 'c'?。 - 如果給定的字串(沒有它的分隔引號)是
A BxyC$B,那么結果字串將是<A> ' ' <B> 'x' 'y' <C> '$' <B>?。 - 如果給定的字串(沒有它的分隔引號)是
XY12,那么結果字串將是<X> <Y> '1' '2'?。
sub MAIN ( )
{
my $myString = 'aSbTc' ;
# Desired output: The string "'a' <S> 'b' <T> 'c'" (sans ").
# Uppercase letters in angle brackets, each other character in single quotes.
}
更新 …
我已經得出以下可能的解決方案,但我懷疑有一個更簡潔(單行?)的解決方案......
sub delimited( $char )
{
if ( $char ~~ /<upper>/ )
{ '<' ~ $char ~ '>' }
else
{ '\'' ~ $char ~ '\'' }
}
sub toDelimitedString( $string )
{
my Seq $seq = $string.split( "", :skip-empty ) ;
my Seq $delimitedSeq = map( &delimited, $seq ) ;
my Str $result = $delimitedSeq.list.join: ' ' ;
$result ;
}
sub MAIN ( )
{
say toDelimitedString( 'aSbTc' ) ; # OUTPUT: 'a' <S> 'b' <T> 'c'
say toDelimitedString( 'A BxyC$B' ) ; # OUTPUT: <A> ' ' <B> 'x' 'y' <C> '$' <B>
say toDelimitedString( 'XY12' ) ; # OUTPUT: <X> <Y> '1' '2'
} # end sub MAIN
uj5u.com熱心網友回復:
我的 oneliner 解決方案是:
say "aSbTc".comb.map({ $_ ∈ "A".."Z" ?? "<$_>" !! "'$_'" }).join(" ")
# 'a' <S> 'b' <T> 'c'
請注意,這僅檢查A通過的字母Z,而不是所有大寫字母。如果你真的想要所有大寫字母:
say "aSbTc".comb.map({ / <:Lu> / ?? "<$_>" !! "'$_'" }).join(" ")
這使用了一個正則運算式,它可能更具可讀性,也可能不更具可讀性。
uj5u.com熱心網友回復:
您需要的替換的癥結如下:
my @myString = $myString.comb;
for @myString {
.=subst(:global, /(<:Lu>)/, {"<$0>"});
.=subst(:global, /(<:Ll :N :Sc :Zs>)/, {"\'$0\'"})
};
put @myString;
作為 Raku 單線完成(注意避免參考問題):
~$ echo 'aSbTc' | raku -e 'my @str1 = lines.comb; for @str1 { .=subst(:global, /(<:Lu>)/, {"<$0>"}); .=subst(:global, /(<:Ll :N :Sc :Zs>)/, {"\c[APOSTROPHE]$0\c[APOSTROPHE]"}) }; put @str1;'
'a' <S> 'b' <T> 'c'
~$ echo 'A BxyC$B' | raku -e 'my @str1 = lines.comb; for @str1 { .=subst(:global, /(<:Lu>)/, {"<$0>"}); .=subst(:global, /(<:Ll :N :Sc :Zs>)/, {"\c[APOSTROPHE]$0\c[APOSTROPHE]"}) }; put @str1;'
<A> ' ' <B> 'x' 'y' <C> '$' <B>
~$ echo 'XY12' | raku -e 'my @str1 = lines.comb; for @str1 { .=subst(:global, /(<:Lu>)/, {"<$0>"}); .=subst(:global, /(<:Ll :N :Sc :Zs>)/, {"\c[APOSTROPHE]$0\c[APOSTROPHE]"}) }; put @str1;'
<X> <Y> '1' '2'
附錄:您顯然可以嘗試更改第二個.=subst命令以對第一個命令的否定采取行動,即/(<:!Lu>)/. 但這接受了種類繁多的字符(包括控制字符),這可能不是您想要的。在實踐中,我發現它很挑剔并且需要一個unless條件(但請參閱下面的作業代碼):
~$ echo -n 'aSbTcA BxyC$BXY12' | raku -e 'my @str1 = $*IN.comb; for @str1 { .=subst(:global, /(<:Lu>)/, {"<$0>"}); .=subst(:global, / (<:!Lu>) /, {"\c[APOSTROPHE]$0\c[APOSTROPHE]"}) unless /<:Lu>/ }; @str1.put;'
'a' <S> 'b' <T> 'c' <A> ' ' <B> 'x' 'y' <C> '$' <B> <X> <Y> '1' '2'
[請注意,此答案不會嘗試使用sub MAIN () { … }. 你仍然必須決定(例如),如果你想讓你的腳本接受命令列輸入,或者發出一個prompt,等等]。
https://docs.raku.org/language/regexes#Unicode_properties
uj5u.com熱心網友回復:
我的解決方案是:
sub MAIN() {
my token left-delimiter { <[ ' < ]> }
my token right-delimiter { <[ ' > ]> }
my token middle-character { <(<-[ ' < > ]> )> }
my token quotation-string { <left-delimiter> ~ <right-delimiter> <middle-character> }
my token target-string { <quotation-string> % \s }
sub extract-characters-between-delimiter(Str $s) {
if $s ~~ / <target-string> / {
say [~] gather for $/<target-string>{'quotation-string'} {
take .{'middle-character'}
}
}
}
my @target-strings = [
Q??'a' <S> 'b' <T> 'c'??,
Q??<A> ' ' <B> 'x' 'y' <C> '$' <B>"??,
Q??<X> <Y> '1' '2'??
];
extract-characters-between-delimiter($_) for @target-strings;
}
更新:感謝您指出我的錯誤,這是我的回答:
sub MAIN() {
my @strings = [
Q??aSbTc??,
Q??A BxyC$B??,
Q??XY12??
];
.comb.map(-> $n { if 65 <= $n.ord <= 90 { "<{$n}>"} else {"'{$n}'"} }).join(' ').say for @strings;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/492593.html
上一篇:使用正則運算式匹配標頭和值,多行
