用sed實現wc -w的功能

来源:http://www.cnblogs.com/Colin-Cai/archive/2017/10/14/7663831.html
-Advertisement-
Play Games

sed是所謂的流編輯器,我們經常用它來做一些文本替換的事情,這是sed最擅長的事情,如sed 's/Bob/Tom/g'就是把文章中所有的Bob改成Tom。 sed是圖靈完備的,作為sed的粉絲,喜歡用sed做各種sed不擅長的事情,這裡實現一下wc -w的功能,也就是統計文章單詞數量。 我習慣喜歡 ...


  版權申明:本文為博主窗戶(Colin Cai)原創,歡迎轉帖。如要轉貼,必須註明原文網址

  http://www.cnblogs.com/Colin-Cai/p/7663831.html 

  作者:窗戶

  QQ:6679072

  E-mail:[email protected]

  sed是所謂的流編輯器,我們經常用它來做一些文本替換的事情,這是sed最擅長的事情,如sed 's/Bob/Tom/g'就是把文章中所有的Bob改成Tom。

  sed是圖靈完備的,作為sed的粉絲,喜歡用sed做各種sed不擅長的事情,這裡實現一下wc -w的功能,也就是統計文章單詞數量。

  我習慣喜歡加上n和r,n表示每行結束時不會自動列印,r表示正則表達式的擴展方式,我實在很討厭寫那麼多\,所以sed基本上我是一定加這兩個東西的。

  先從sed擅長的開始,先用s命令做替換,把每個單詞都替換為單個1。這一步其實很簡單,s/[^ \t\r]+/1/g即可,也就是把不是空格的連續匹配替換為1,g是表示對一行中所有滿足這樣的模式都替換為1,再考慮到正則表達式的貪婪,其實我們的[^ \t\r]+實際上就是指完整的一個單詞,熟悉regex替換的應該不難理解。

  然後為了整齊,替換為1之後,再把空格都去掉,其實也就是把不是1的去掉,那麼緊接著一條s/[^1]+//g即可,然後再用p列印一下。

  一口吃不成胖子,先從簡單的來,我們可以看一下效果。在此之前先找篇文章,就節選一下google的pixel buds新聞吧。

linux-p94b:/tmp/testhere # cat 1.txt
American company Google recently announced the release of its Google Pixel 2 phone and other products that work together with the phone.
One of the new products is a pair of wireless earphones Google calls Pixel Buds.
The earphones are seen as the company's answer to competitor Apple's popular AirPod headphones.
At a launch event on October 4, Google said its Pixel Buds were built to provide high-quality sound and hands-free use. All of their operations can be controlled by simply touching the right earphone.
Once the headphones are paired with a Pixel phone, its many features can be used through the Pixel Buds.
One example is Google Assistant, the company's artificial intelligence, or AI, service. Users can now talk directly to Pixel Buds to ask Google Assistant questions, get information or other help. This can all be done without touching the telephone.
The Pixel Buds also can work with Google Translate, the service that provides words and expressions in over 100 languages.
Google product manager Juston Payne demonstrated this feature during the launch event. He was able to talk with someone whose native language is Swedish.
When the person spoke Swedish into the Pixel Buds, the phone's speakers provided the translation in English. The English speaker's response was then translated in real time into Swedish and heard through the Pixel Buds.
linux-p94b:/tmp/testhere # cat wc-w.sed
#!/usr/bin/sed -nrf
s/[^ \t\r]+/1/g
s/[^1]+//g
p
linux-p94b:/tmp/testhere # ./wc-w.sed <1.txt
1111111111111111111111
111111111111111
11111111111111
1111111111111111111111111111111111
1111111111111111111
111111111111111111111111111111111111111
11111111111111111111
111111111111111111111111
11111111111111111111111111111111111

  對一下,確實沒有錯,只是出來了一堆1,而且還是分行的,那麼第二步,把這個分行給去掉。當然,加個管道,tr -d '\n'就去掉了,不過我們要的是單個sed解決,那麼需要再動一點點腦筋。

  我們可以在上面的基礎上稍微改動改動,把這些1先緩存進保持空間(hold space),最後再從保持空間中取出,然後用s/\n//g去掉所有的回車符,再列印。

linux-p94b:/tmp/testhere # cat wc-w.sed
#!/usr/bin/sed -nrf
s/[^ \t\r]+/1/g
s/[^1]+//g
H
$ {
        g
        s/\n//g
        p
}
linux-p94b:/tmp/testhere # ./wc-w.sed <1.txt
111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

  H命令就是放在保持空間的最後,$是判定輸入結束,g是用保持空間的內容替換模式空間。

  上面列印出了222個1,離結果222已經很近了。

  最後就是如何整合成222了,這裡的確是需要一點點技巧了。我們建立以下計數方法:

  1..1;1..1;1..1...

        每一堆1的個數假設為nk,nk-1,...,n0

  允許數量為0的堆

  每一堆1之間用分號隔開,如果看到有多個分號在一起,那麼中間實際上有數量為0的堆

  整個計數表示的是nk*10k+nk-1*10k-1+...+n0

  很明顯,我們十進位表示方法和整個很類似,只是,十進位表示里,每一堆都小於10而已。

  於是我們可以創立一個演算法,也就是,當我們發現一堆里有10個1,那麼我們就可以往高位進1。

  很容易證明這個演算法可以結束。

  假設{nk,nk-1,...,n0}有限序列是非負整數num的一個表示,序列里的每一個數字是一個非負整數,最高位nk大於0,除非num等於0。

  顯然,一個具體整數的表示方法是有限的,實際上,這個k不可能大於num對10取對數,序列中的每一項不可能大於num。

  序列可以比較大小,

  {mj,mj-1,...,m0}有限序列是num的另外一個表示,那麼

  {nk,nk-1,...,n0} 〉{mj,mj-1,...,m0} 當且僅當 k > j  或者    k = j且nk=mk...nk-p=mk-p,nk-p-1>mk-p-1

  以上比較大小的方法可以把一個非負整數的所有表示串成一個全序集。

  之前的演算法中,每當升位,其表示都會變的比之前大。因為所有的表示為有限個,而最大的表示則是十進位的表示方法,從而可以知道演算法是可以結束得到十進位表示的。

 

  那麼我們根據這個,不停的找10個0,每當找到,就進位,最後再把每堆挨個替換為9,8,7,6,5,4,3,2,0,再去掉分號,就完成了。有點費腦子吧,我實現一下如下:

linux-p94b:/tmp/testhere # cat wc-w.sed
#!/usr/bin/sed -nrf
s/[^ \t\r]+/1/g
s/[^1]+//g
H
$ {
        g
        s/\n//g
        :a
        s/;1111111111/1;/
        s/^1111111111/1;/
        ta
        s/111111111/9/g
        s/11111111/8/g
        s/1111111/7/g
        s/111111/6/g
        s/11111/5/g
        s/1111/4/g
        s/111/3/g
        s/11/2/g
        :b
        s/;;/;0;/g
        tb
        s/;$/;0/
        s/;//g
        /^$/s/^/0/
        p
}
linux-p94b:/tmp/testhere # ./wc-w.sed <1.txt
222

  

  


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • java實現驗證碼功能 通過java代碼實現驗證碼功能的一般思路: 一、通過java代碼生成一張驗證碼的圖片,將驗證碼的圖片保存到項目中的指定文件中去,代碼如下: 二、將項目中指定文件夾中剛剛生成的驗證碼圖片的路徑在登錄頁面顯示出來,並將生成驗證碼返回的字元串保存在一個字元串變數中,假設保存在變數A ...
  • Python中return的作用 ...
  • 1.一個子類對象的類型可以向上轉換成它的父類類型,也即一個子類對象可以當做父類對象的引用,這種轉換是安全的,Java編譯器能自動進行 2.一個父類對象的類型一般不能向下轉換成它的子類類型,也即一個父類對象一般不能當做子類對象使用。但當父類對象引用的是子類對象,是可以進行強制類型轉換的,否則,編譯可以 ...
  • 在java語言中,事件不是由事件源自己來處理的,而是交給事件監聽者來處理,要將事件源(如按鈕)和對事件的具體處理分離開來。這就是所謂的事件委托處理模型。 事件委托處理模型由產生事件的事件源、封裝事件相關信息的事件對象和事件監聽者三方面構成。例如,當按鈕被滑鼠點擊時,會觸發一個“操作事件(Action ...
  • Python的函數參數例子講解 ...
  • 為什麼使用介面? 問題 要求實現防盜門的功能 分析 門有開和關的功能,鎖有上鎖和開鎖的功能 將門和鎖分別定義為抽獎類 那麼問題就是防盜門即繼承了門的同時又繼承了鎖,而Java的繼承是單繼承,介面可多繼承。 解決 將門定義為抽獎類,鎖定義為介面 防盜門繼承門,實現鎖的介面 解決了多繼承 什麼是介面? ...
  • 接上篇 三、連接oracle之配置文件 為了增加程式的可移植性,將 db = cx_Oracle.connect('bss_cpc/[email protected]/orcl') 修改為: db = cx_Oracle(connStr),connStr值從配置文件中讀取。 讀取配置文件可 ...
  • Moke測試學習總結: 被測試代碼: public class LoginPresenter { private UserManager mUserManager = new UserManager(); public void login(String username, String passw ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...