Linux

列印行中每個大寫字母都以不同字母開頭的行

  • October 22, 2021

我有這段文字:

FOUR MILLION, EIGHT HUNDRED AND FIFTY-SEVEN THOUSAND, FIVE HUNDRED AND THIRTEEN innovating
FORTY-NINE MILLION, ONE HUNDRED AND EIGHTY THOUSAND, TWO HUNDRED AND FORTY-EIGHT championed
FORTY-SEVEN MILLION, NINE HUNDRED AND FIFTY-TWO THOUSAND, EIGHT HUNDRED AND SIX swashbuckling
NINE HUNDRED AND SIXTY-ONE THOUSAND, SIX HUNDRED AND THIRTY-ONE sprinklers
FORTY-TWO MILLION, TWO HUNDRED AND SIXTY-SIX THOUSAND, THREE HUNDRED AND SEVENTY-TWO furloughs
SEVEN MILLION, FOUR HUNDRED AND SEVENTEEN THOUSAND, FOUR HUNDRED AND FORTY-TWO panicky
THREE HUNDRED AND SEVENTY-NINE THOUSAND, FIVE HUNDRED AND TWENTY-EIGHT anchovies
FIVE MILLION, EIGHT HUNDRED AND FIFTY-NINE THOUSAND, FOUR HUNDRED AND SIXTY-FOUR excesses

............

如何使用grepsed列印大寫字母行的每個單詞都以不同字母開頭的行?

例如:

FIFTY THOUSAND, NINE HUNDRED AND EIGHTEEN
FOURTEEN THOUSAND, SEVEN HUNDRED AND NINETY-EIGH

您可以使用正則表達式對輸入進行掃描並獲得所需的輸出。

我們告訴grep尋找一個大寫單詞,它的第一個字元在該行的下方但僅在另一個大寫單詞的開頭。由於這意味著至少有一個這樣的匹配,但我們不希望這樣-v的匹配,所以我們反轉匹配的意義以獲得所需的輸出。

編輯:根據@they 的觀察,它被修改為查找大寫單詞。

grep -v  '\<\([A-Z]\)[A-Z]\{1,\}\>.*\<\1[A-Z]\{1,\}\>'  file

解決此類問題的首要任務是為工作選擇正確的工具。在這個問題中,我們需要計算每個單詞的首字母在一行中出現的次數。兩者都以不擅長計數grepsed著稱,至少它們本身是不擅長計數的,而awk更像是一種通用程式語言。如果我們想使用任何單一的工具來解決任務,awk可能會更適合。

awk '{
   delete count
   for (i = 1; i <= NF; ++i) {
       ch = substr($i,1,1)
       if (ch == toupper(ch) && count[ch]++)
           next
   }
   print
}' file

該程式碼計算每行上所有單詞的初始大寫字母的出現次數(單詞是由空格分隔的子字元串)。我們將計數保存在關聯數組count中,由數據中的字母索引。

一旦我們第二次遇到其中一個首字母,我們就會丟棄該行。我們以這種方式列印我們不丟棄的每一行。

此程式碼只關心單詞的第一個字元是否為大寫。要測試全部大寫的單詞的第一個字元,請改用以下命令:

awk '{
   delete count
   for (i = 1; i <= NF; ++i)
       if ($i != toupper($i) && count[substr($i,1,1)]++)
           next
   print
}' file

下一個問題是理解程式碼。您現在已經獲得了程式碼,並且它可以工作,但您可能不知道為什麼。更重要的是,您可能不知道如何修改它以做一些稍微不同的事情,或者如果它在您發現的某些極端情況下突然失敗,如何糾正它。

您可以通過查找awk手冊中的每一位作為開始來更好地了解程式碼。然後,當你不明白我為什麼delete count在那個特定的地方而不是其他地方寫的時候,你可以問另一個關於這個的問題,或者更好的是,對程式碼進行試驗並註意它以什麼特定方式破壞。

引用自:https://unix.stackexchange.com/questions/674283