簡體   English   中英

如何將存儲為文本的數字划分為 awk 或 sed 或其他中的多個部分?

[英]How to divide numbers stored as text into many parts in awk or maybe sed or other?

我需要划分我的文本文件。 在我的文本文件中,我有數字。 這是我輸入文件的一小部分。 在我的文本文件中,我有從 29026 到 58050 的數字。

29026 29027 29028 29029 29030 29031 29032 29033 29034 29035 29036 29037 29038 29039 29040
29041 29042 29043 29044 29045 ...........................................................
................................................58029 58030 58031 58032 58033 58034 58035
58036 58037 58038 58039 58040 58041 58042 58043 58044 58045 58046 58047 58048 58049 58050

我必須創建 225 個索引組。 每組必須有 129 個號碼。 所以我的 output 看起來像

[ Lipid 1 ]
29026 29027 29028 29029 ...................................
...............
...........................29150 29151 29152 29153 29154
[ Lipid 2 ]
...
...


[ Lipid 225 ]
57921 57922 57923 57924 57925 57926......
.....
.......................
58044 58045 58046 58047 58048 58049 58050

你有什么主意嗎?

編輯我的文本文件

29026 29027 29028 29029 29030 29031 29032 29033 29034 29035 29036 29037 29038 29039 29040
29041 29042 29043 29044 29045 29046 29047 29048 29049 29050 29051 29052 29053 29054 29055
29056 29057 29058 29059 29060 29061 29062 29063 29064 29065 29066 29067 29068 29069 29070
29071 29072 29073 29074 29075 29076 29077 29078 29079 29080 29081 29082 29083 29084 29085
29086 29087 29088 29089 29090 29091 29092 29093 29094 29095 29096 29097 29098 29099 29100
29101 29102 29103 29104 29105 29106 29107 29108 29109 29110 29111 29112 29113 29114 29115
29116 29117 29118 29119 29120 29121 29122 29123 29124 29125 29126 29127 29128 29129 29130
29131 29132 29133 29134 29135 29136 29137 29138 29139 29140 29141 29142 29143 29144 29145
29146 29147 29148 29149 29150 29151 29152 29153 29154 29155 29156 29157 29158 29159 29160
29161 29162 29163 29164 29165 29166 29167 29168 29169 29170 29171 29172 29173 29174 29175
29176 29177 29178 29179 29180 29181 29182 29183 29184 29185 29186 29187 29188 29189 29190
29191 29192 29193 29194 29195 29196 29197 29198 29199 29200 29201 29202 29203 29204 29205
29206 29207 29208 29209 29210 29211 29212 29213 29214 29215 29216 29217 29218 29219 29220
29221 29222 29223 29224 29225 29226 29227 29228 29229 29230 29231 29232 29233 29234 29235
29236 29237 29238 29239 29240 29241 29242 29243 29244 29245 29246 29247 29248 29249 29250
29251 29252 29253 29254 29255 29256 29257 29258 29259 29260 29261 29262 29263 29264 29265
29266 29267 29268 29269 29270 29271 29272 29273 29274 29275 29276 29277 29278 29279 29280
29281 29282 29283 29284 29285 29286 29287 29288 29289 29290 29291 29292 29293 29294 29295
29296 29297 29298 29299 29300 29301 29302 29303 29304 29305 29306 29307 29308 29309 29310
29311 29312 29313 29314 29315 29316 29317 29318 29319 29320 29321 29322 29323 29324 29325
29326 29327 29328 29329 29330 29331 29332 29333 29334 29335 29336 29337 29338 29339 29340
29341 29342 29343 29344 29345 29346 29347 29348 29349 29350 29351 29352 29353 29354 29355
29356 29357 29358 29359 29360 29361 29362 29363 29364 29365 29366 29367 29368 29369 29370
29371 29372 29373 29374 29375 29376 29377 29378 29379 29380 29381 29382 29383 29384 29385
29386 29387 29388 29389 29390 29391 29392 29393 29394 29395 29396 29397 29398 29399 29400
29401 29402 29403 29404 29405 29406 29407 29408 29409 29410 29411 29412 29413 29414 29415
29416 29417 29418 29419 29420 29421 29422 29423 29424 29425 29426 29427 29428 29429 29430

here I have thousands of lines, but I will not paste all of this text

57736 57737 57738 57739 57740 57741 57742 57743 57744 57745 57746 57747 57748 57749 57750
57751 57752 57753 57754 57755 57756 57757 57758 57759 57760 57761 57762 57763 57764 57765
57766 57767 57768 57769 57770 57771 57772 57773 57774 57775 57776 57777 57778 57779 57780
57781 57782 57783 57784 57785 57786 57787 57788 57789 57790 57791 57792 57793 57794 57795
57796 57797 57798 57799 57800 57801 57802 57803 57804 57805 57806 57807 57808 57809 57810
57811 57812 57813 57814 57815 57816 57817 57818 57819 57820 57821 57822 57823 57824 57825
57826 57827 57828 57829 57830 57831 57832 57833 57834 57835 57836 57837 57838 57839 57840
57841 57842 57843 57844 57845 57846 57847 57848 57849 57850 57851 57852 57853 57854 57855
57856 57857 57858 57859 57860 57861 57862 57863 57864 57865 57866 57867 57868 57869 57870
57871 57872 57873 57874 57875 57876 57877 57878 57879 57880 57881 57882 57883 57884 57885
57886 57887 57888 57889 57890 57891 57892 57893 57894 57895 57896 57897 57898 57899 57900
57901 57902 57903 57904 57905 57906 57907 57908 57909 57910 57911 57912 57913 57914 57915
57916 57917 57918 57919 57920 57921 57922 57923 57924 57925 57926 57927 57928 57929 57930
57931 57932 57933 57934 57935 57936 57937 57938 57939 57940 57941 57942 57943 57944 57945
57946 57947 57948 57949 57950 57951 57952 57953 57954 57955 57956 57957 57958 57959 57960
57961 57962 57963 57964 57965 57966 57967 57968 57969 57970 57971 57972 57973 57974 57975
57976 57977 57978 57979 57980 57981 57982 57983 57984 57985 57986 57987 57988 57989 57990
57991 57992 57993 57994 57995 57996 57997 57998 57999 58000 58001 58002 58003 58004 58005
58006 58007 58008 58009 58010 58011 58012 58013 58014 58015 58016 58017 58018 58019 58020
58021 58022 58023 58024 58025 58026 58027 58028 58029 58030 58031 58032 58033 58034 58035
58036 58037 58038 58039 58040 58041 58042 58043 58044 58045 58046 58047 58048 58049 58050

以下是我對您的問題的理解:

輸入是一個多行文本文件,每行有 15 個數字,由空格或制表符分隔。 某些行(可能是最后一行)的數字可能少於 15 個。 (事實上,在下面的解決方案中,每行有多少數字並不重要。)

您必須按順序將這些數字分成一組,每組 129 個數字。 如果輸入基數不是 129 的精確倍數,最后一組可能有少於 129 個數字。在下面的解決方案中,有多少輸入數字無關緊要(因此輸出中有多少組)。

對於每組 129 個數字,您必須在 output 中獲取幾行。 首先,標題或 label 顯示[Lipid n]其中n是行號,然后是該組中的數字,每行顯示 15 個(因此,將有 8 個完整的行和第 9 個行,上面只有 9 個數字: 129 = 15 * 8 + 9)。

這是您如何做到這一點的方法。 首先讓我們從一個小例子開始,然后我們可以看看為了更通用的解決方案必須改變什么。

我將假設您的輸入可以是任意長度的任意數字; 當然,如果它們是像您在示例數據中顯示的連續數字,那么問題是微不足道的並且完全無趣。 所以讓我們假設你的數字實際上是任何數字。 (不是真的;我為非負整數編寫了解決方案;但它可以重寫為由空格分隔的非空白字符的“標記”。)

我從以下輸入文件開始:

$ cat lipid-inputs 
124 150 178 111 143 177 116
154 194 139 183 132 180 133
185 142 101 159 122 184 151
120 188 161 136 113 189 170

我們希望將 28 個輸入數字分組為每組十個數字,並呈現 output 每行(最多)七個數字。 所以:將有兩個完整的組,第三個組只有八個成員編號(因為我們只有 28 個輸入)。 所需的 output 如下所示:

[Lipid 1]
124 150 178 111 143 177 116
154 194 139
[Lipid 2]
183 132 180 133 185 142 101
159 122 184
[Lipid 3]
151 120 188 161 136 113 189
170  

策略:首先每行寫一個輸入數字,然后我們可以將它們每行排列十個(十:輸出中所需組的基數)。 然后添加行號(將 go 加入 label 行)。 然后編輯“行號”行以添加“脂質”內容,並將數據行分成較短的行,每行顯示七個標記(每組的最后一行可能更少)。

實現: tr每行分解一個令牌; paste從標准輸入重復讀取的內容,每條 output 行十個標准輸入行; 然后sed =添加行號(在單獨的行上); 最后是標准的sed用於最終編輯。 該命令如下所示:

$ tr -s ' ' '\n' < lipid-inputs | paste -d ' ' - - - - - - - - - - | 
> sed = | sed -E 's/^[[:digit:]]+$/[Lipid &]/ ;
>                 s/(([[:blank:]]*[[:digit:]]+){7}) /\1\n/g'

output 是我已經展示的那個。

概括(以便您可以應用於您的問題):輸入文件中每行的標記數無關緊要。 要在output中的每行獲取 15 個令牌,請將上面顯示的命令中最后一行的硬編碼數字 7 更改為 15。 並且要為每行分配 129 個令牌,而不是 10 個,需要更改的是paste命令:我顯示它從標准輸入讀取十次。 您需要 129。因此,最好在一個簡單的命令中創建一個由空格分隔的 129 個破折號的字符串 - 而不是硬編碼 - 並將該字符串用作paste的輸入。 我為我的例子展示了如何做到這一點,你會適應你的。

定義變量以保存您的相關值:每個脂質有多少令牌(在您的情況下為 129,在我的情況下為 10)以及 output 中每行有多少令牌(在您的情況下為 15,在我的情況下為 7)。

$ tokens_per_lipid=10
$ tokens_per_line=7

然后創建一個變量來保存paste命令中所需的字符串- - - - [...] 有幾種方法可以做到這一點,這里只是一種:

$ paste_arg=$(yes '-' | head -n $tokens_per_lipid | tr '\n' ' ')

讓我們檢查一下:

$ echo $paste_arg
- - - - - - - - - -

好的,所以讓我們重新編寫執行您需要的命令。 我們必須對sed的參數使用雙引號以允許變量擴展。

$ tr -s ' ' '\n' < lipid-inputs | paste -d ' ' $paste_arg |
> sed = | sed -E "s/^[[:digit:]]+$/[Lipid &]/ ;
>                 s/(([[:blank:]]*[[:digit:]]+){$tokens_per_line}) /\1\n/g"
[Lipid 1]
124 150 178 111 143 177 116
154 194 139
[Lipid 2]
183 132 180 133 185 142 101
159 122 184
[Lipid 3]
151 120 188 161 136 113 189
170  

我不知道你真正想要做什么,但也許這就是你想要的

< input sed -zE 's/(([0-9]+[^0-9]+){129})/[ Lipid # ]\n\1\n/g' | awk 'BEGIN { RS = ORS = "]" } { sub("#", NR) } 1' | sed '$d'

它使用 Sed 每 129 次出現[0-9]+[^0-9]+插入[ Lipid # ]字符串(帶有一些換行符)(即 1 個或多個數字后跟 1 個或多個非數字); 然后它使用 Awk 將#替換為從 1 開始的數字(為此,它將]解釋為記錄分隔符,因此它可以將#更改為記錄的編號NR ); 最后,它再次使用 Sed 從 Awk 處理中刪除作為最后一條記錄分隔符出現的最后一行。

我使用 Awk 來插入不斷增加的數字,因為在 Sed 中進行數學運算並不容易; 我使用 Sed 來中斷文件並根據要求在其間插入文本,因為我發現它比在 Awk 中更容易。

如果您需要在 output 中將所有數字放在一行上,您可以這樣做

< input sed -zE 's/[^0-9]+/ /g;s/(([0-9]+[^0-9]+){129})/[ Lipid # ]\n\1\n/g' | awk 'BEGIN { RS = ORS = "]" } { sub("#", NR) } 1' | sed '$d'

我剛剛添加了s/[^0-9]+/ /g; 將數字之間發生的任何事情折疊成一個空格。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM