
我的輸入看起來像這樣:
Austin, Ashley D
Bender, Isaiah J
在這裡,我嘗試將第一個名字剪切到“,”,然後添加第二個名字的第一個字母。
例如,上面的兩個將是奧斯汀娜和本德里。有人可以幫忙嗎?
答案1
您已表示有興趣通過 解決此問題cut
。應該有一種方法可以做到這一點管道和一些組合cut
,tr
, 有可能)paste
。但特別是因為您要修改首字母的大小寫(例如,Ashley 中的前導“A”變為“Austina”中的尾隨“a”),因此使用比 更通用的內容更容易cut
。我建議一個 Perl 單行程式碼,可能是這樣的或類似的東西,主要取決於您希望在名稱中允許使用哪些字元:
perl -wpe 's/^(\w+),\s*(\w).*/$1\L$2/' file
它運行 Perl 解釋器,啟用警告 ( -w
),逐行讀取輸入,在每一行上執行腳本並列印結果 ( -p
),並從下一個命令列參數 ( -e
) 取得其腳本。腳本本身,s/^(\w+),\s*(\w).*/$1\L$2/
我引用和單引號所以 shell 不會執行自己的操作擴充在其上,由一個表達式組成,該表達式將其輸入匹配到s/pattern/replacement/
圖案並將匹配替換為替代品。
在裡面正規表示式, ^(\w+),\s*(\w).*
:
^
匹配行的開頭。(\w+)
配對一個或多個 (+
) 單字字元 (\w
,見下文),並捕獲它們((
)
)進入第一個捕獲組。,
從字面上看,它本身是匹配的。\s*
匹配零個或多個 (*
) 空白字元 (\s
)。(\w)
完全匹配一個單字字元 (\w
,見下文),並捕獲它((
)
)進入第二個捕獲組。.*
匹配零個或多個 (*
) 可能出現在一行 (.
)。換句話說,它與該行的其餘部分匹配。
然後$1\L$2
導致所有匹配的文字(整行,假設它做過匹配)替換為:
$1
,第一個捕獲組的內容,不加修改。此欄位旨在包含一個人的姓氏。\L$2
,第二個捕獲組 ( ) 的內容$2
,轉換為小寫 (\L
)。這是第一個字符,旨在包含一個人的名字(但變為小寫)。
這可能很適合你。但:
- 您可能需要修改
\w
模式中出現的兩個 ,具體取決於您希望在名稱中匹配的字元。\w
只符合字母、數字和底線(_
)。許多名稱都有除此之外的其他字符,例如破折號和撇號。 - 還有一個問題是什麼才算是一封信(儘管有時有不同的解決方案,但它也適用於更簡單的工具)。看僅匹配正規表示式中的字母的最佳方法是什麼?這與包含重音字母、附加到字母的變音符號以及非拉丁字母表中的字母的名稱有關。
- 大小寫轉換是一個比看起來更難的問題。不同的書寫語言不僅有不同的字母,而且某些相同字母的大小寫轉換也不同。
另一個很簡單的選擇代替\w
我能想到的東西——允許名稱包含任何內容其他比空格或-- 可以透過將每個替換,
為 來實現。使一個\w
[^,\S]
[
]
字元類, 前導^
表示該類別包含所有但指定的字元(即不是與其在字元類別之外的含義相關),,
按字面指定自身,並且\s
指定所有空白字元。
perl -wpe 's/^([^,\s]+),\s*([^,\s]).*/$1\L$2/' file
有關 Perl 中正規表示式的更多信息,請參閱perldoc perlretut
和perldoc perlre
。您提出的問題是只是複雜到足以激勵我使用比基本文字處理工具更複雜(因此更複雜)的工具。由於您可能會找到一種使用這些工具來完成此操作的方法,因此如果您這樣做了,我當然不會責怪您!但我認為這對未來甚至更複雜的問題仍然可能有幫助。
答案2
建議使用 cut、pipes、tr、paste(和 sed)的解決方案可能是:
cut -f1 -d, foo >bar; cut -f2 -d" " foo | cut -c1 |tr "A-Z" "a-z" >bar2 ;paste bar bar2|sed -e "s/\x9//g"
foo 是包含您輸入的檔案。因此,您可以透過切割和其他方式來完成任務,但珍珠解決方案更加優雅和合適。