簡體   English   中英

從長行按位置刪除字段

[英]Delete a field by position from a long line

我有一個長的分號分隔的字段,其中69個是准確的。

我需要刪除字段3,所以我可以以冗長的方式執行:

awk -F\; '$1 == 3 { print $1";"$2";"$4 ... }' a.txt

哪個會變得很長。 有沒有捷徑可以說“4美元到底”,“4美元到69美元”或者只是“刪除3美元”?

與問題相關:重復“;” 到處都是非常不方便的。

當然,我可以部分生成命令:

echo -e "\b"{4..69}"\";\"$"

雖然它看起來很聰明,但結果卻是一個多線命令,這個命令並不優雅。

什么是優雅的解決方案 - 最好是純粹的awk。

我想我可以快速找到一個sed解決方案,但我有更多的事情要做(重新計算字段5:如果字段1 == 2,Field5 = 5-Field5),這在sed中很難,但我覺得很合適對於awk。

我正在使用Gnu-AWK 3.1.6,如果它很重要,但根據apropos:

  • AWK
  • 呆子
  • igawk
  • mawk
  • NAWK
  • pgawk

好的,更新:

我應該知道的更好,並立即提供一些測試數據,但當然,我會嘗試你所有的答案,並提出看起來很有希望的東西。

3;03.2012;7228;0;1;3;1;3;4;3;1;3;4;3;2;0;4;4;1;1;4;2;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;1;1;3;0;3;1;3;0;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
3;03.2012;7229;0;2;2;0;5;5;4;4;5;5;4;4;2;5;5;0;0;3;3;0;0;5;6;0;0;0;0;0;2;2;1;2;1;2;2;2;4;3;4;1;5;4;2;0;0;0;0;0;0;0;0;0;0;4;4;4;4;4;0;0;0;0;0;0;0;
3;03.2012;7230;0;2;2;2;4;3;4;4;4;3;3;3;2;4;6;1;1;1;6;5;1;6;6;1;1;1;1;1;2;2;1;2;2;0;2;2;3;4;2;1;4;3;2;0;0;0;0;0;0;0;0;0;0;4;3;3;4;4;0;0;0;0;0;0;0;
3;03.2012;7231;0;1;3;1;4;4;3;3;4;4;4;4;2;5;5;1;1;4;6;5;1;4;1;1;1;1;1;5;2;1;1;2;0;0;1;2;4;4;3;1;4;3;2;0;0;0;0;0;0;0;0;0;0;4;4;4;4;3;0;0;0;0;0;0;0;

抓住這條線。 :)

我很抱歉打斷這種反常的高爾夫比賽。 你是masochists樂於重新發明輪子? 文明為現代人提供污水收集和CSV庫等設施,因此他無需處理 -

如何作為csvfix 它是一個命令行工具,可以處理流入和流出的文本,即。 和awk一樣的環境。 您需要的命令是exclude

csvfix exclude -f 3 -rsep ";" a.txt

單程:

awk '{ 
  split( $0, f, /;/ );
  delete f[3];
  for (i=1; i<=length(f); i++) { 
    printf "%s", f[i] ? f[i] ";" : "" 
  } 
}' <<<"one;two;three;four;five;six;seven"

輸出如下:

one;two;four;five;six;seven;

您可以使用cut命令:

cut -d';' -f1,2,4- a.txt

字段列表可以是范圍,並且可以包括開放范圍(如此處使用的4-)

如果你仍然需要在awk中處理結果,你可以將輸出從中輸入到它中。

你可以使用這樣的東西:

awk -v fl=<filed_list> 'BEGIN {
  n = split(fl, t, " ")
  for (i = 0; ++i <= n;)
    fa[t[i]]
  }
{
  for (i = 0; ++i <= NF;)
    if (!(i in fa))
      printf "%s", ($i (i < NF ? OFS : ORS))
  }' 

考慮以下輸入:

zsh-4.3.14[t]% paste -sd\; < <(printf '%s\n' {1..10})
1;2;3;4;5;6;7;8;9;10

要刪除第3個字段:

zsh-4.3.14[t]% paste -sd\; < <(printf '%s\n' {1..10}) |
pipe>   awk -F\; -v fl=3 'BEGIN {
pipe quote>     n = split(fl, t, " ")
pipe quote>     for (i = 0; ++i <= n;)
pipe quote>       fa[t[i]]
pipe quote>     }
pipe quote>   {
pipe quote>     for (i = 0; ++i <= NF;)
pipe quote>       if (!(i in fa))
pipe quote>     printf "%s", ($i (i < NF ? OFS : ORS))
pipe quote>   }' OFS=\;
1;2;4;5;6;7;8;9;10

要刪除一組字段:

zsh-4.3.14[t]% paste -sd\; < <(printf '%s\n' {1..10}) |
pipe>   awk -F\; -v fl='7 4 3' 'BEGIN {
pipe quote>     n = split(fl, t, " ")
pipe quote>     for (i = 0; ++i <= n;)
pipe quote>       fa[t[i]]
pipe quote>     }
pipe quote>   {
pipe quote>     for (i = 0; ++i <= NF;)
pipe quote>       if (!(i in fa))
pipe quote>     printf "%s", ($i (i < NF ? OFS : ORS))
pipe quote>   }' OFS=\;
1;2;5;6;8;9;10

讓我知道如果刪除最后一個字段(有或沒有尾隨FS),輸出應該如何。

考慮使用單個字符字段分隔符,對於簡單任務, 剪切就足夠了:

zsh-4.3.14[t]% paste -sd\; < <(printf '%s\n' {1..10}) | cut -d\; -f 1-2,4-
1;2;4;5;6;7;8;9;10
zsh-4.3.14[t]% paste -sd\; < <(printf '%s\n' {1..10}) | cut -d\; -f 1-2,5-6,8-
1;2;5;6;8;9;10

[編輯:點擊這里的評論]

鑒於樣本輸入:

3;03.2012;7228;0;1;3;1;3;4;3;1;3;4;3;2;0;4;4;1;1;4;2;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;1;1;3;0;3;1;3;0;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
3;03.2012;7229;0;2;2;0;5;5;4;4;5;5;4;4;2;5;5;0;0;3;3;0;0;5;6;0;0;0;0;0;2;2;1;2;1;2;2;2;4;3;4;1;5;4;2;0;0;0;0;0;0;0;0;0;0;4;4;4;4;4;0;0;0;0;0;0;0;
3;03.2012;7230;0;2;2;2;4;3;4;4;4;3;3;3;2;4;6;1;1;1;6;5;1;6;6;1;1;1;1;1;2;2;1;2;2;0;2;2;3;4;2;1;4;3;2;0;0;0;0;0;0;0;0;0;0;4;3;3;4;4;0;0;0;0;0;0;0;
3;03.2012;7231;0;1;3;1;4;4;3;3;4;4;4;4;2;5;5;1;1;4;6;5;1;4;1;1;1;1;1;5;2;1;1;2;0;0;1;2;4;4;3;1;4;3;2;0;0;0;0;0;0;0;0;0;0;4;4;4;4;3;0;0;0;0;0;0;0;

和以下awk腳本:

zsh-4.3.14[t]% cat s.awk 
BEGIN {
  n = split(fl, t, " ")
  for (i = 0; ++i <= n;)
    fa[t[i]]
  }
{
  for (i = 0; ++i <= NF;)
    if (!(i in fa))
      printf "%s", ($i (i < NF ? OFS : ORS))
  } 

使用此命令:

zsh-4.3.14[t]% awk -F\; -v fl=3 -f s.awk OFS=\; infile > outfile

...我得到以下輸出:

zsh-4.3.14[t]% cat outfile
3;03.2012;0;1;3;1;3;4;3;1;3;4;3;2;0;4;4;1;1;4;2;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;1;1;3;0;3;1;3;0;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
3;03.2012;0;2;2;0;5;5;4;4;5;5;4;4;2;5;5;0;0;3;3;0;0;5;6;0;0;0;0;0;2;2;1;2;1;2;2;2;4;3;4;1;5;4;2;0;0;0;0;0;0;0;0;0;0;4;4;4;4;4;0;0;0;0;0;0;0;
3;03.2012;0;2;2;2;4;3;4;4;4;3;3;3;2;4;6;1;1;1;6;5;1;6;6;1;1;1;1;1;2;2;1;2;2;0;2;2;3;4;2;1;4;3;2;0;0;0;0;0;0;0;0;0;0;4;3;3;4;4;0;0;0;0;0;0;0;
3;03.2012;0;1;3;1;4;4;3;3;4;4;4;4;2;5;5;1;1;4;6;5;1;4;1;1;1;1;1;5;2;1;1;2;0;0;1;2;4;4;3;1;4;3;2;0;0;0;0;0;0;0;0;0;0;4;4;4;4;3;0;0;0;0;0;0;0;

如果我正確理解了要求,則輸出正確。

要從1到5中刪除字段:

zsh-4.3.14[t]% awk -F\; -v fl='1 2 3 4 5' -f s.awk OFS=\; infile > outfile
zsh-4.3.14[t]% cat outfile
3;1;3;4;3;1;3;4;3;2;0;4;4;1;1;4;2;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;1;1;3;0;3;1;3;0;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
2;0;5;5;4;4;5;5;4;4;2;5;5;0;0;3;3;0;0;5;6;0;0;0;0;0;2;2;1;2;1;2;2;2;4;3;4;1;5;4;2;0;0;0;0;0;0;0;0;0;0;4;4;4;4;4;0;0;0;0;0;0;0;
2;2;4;3;4;4;4;3;3;3;2;4;6;1;1;1;6;5;1;6;6;1;1;1;1;1;2;2;1;2;2;0;2;2;3;4;2;1;4;3;2;0;0;0;0;0;0;0;0;0;0;4;3;3;4;4;0;0;0;0;0;0;0;
3;1;4;4;3;3;4;4;4;4;2;5;5;1;1;4;6;5;1;4;1;1;1;1;1;5;2;1;1;2;0;0;1;2;4;4;3;1;4;3;2;0;0;0;0;0;0;0;0;0;0;4;4;4;4;3;0;0;0;0;0;0;0;

我錯過了什么嗎?

Pure Bash:

IFS=';'
while read -a line ; do
  unset line[2]
  echo "${line[*]}"
done < infile.dat
awk -F";" 'BEGIN{OFS=";"} {$3="";print }' file3|sed 's/;;/;/'

這是測試:

pearl.341> cat file3
3;03.2012;7228;0;1;3;1;3;4;3;1;3;4;3;2;0;4;4;1;1;4;2;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;1;1;3;0;3;1;3;0;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
3;03.2012;7229;0;2;2;0;5;5;4;4;5;5;4;4;2;5;5;0;0;3;3;0;0;5;6;0;0;0;0;0;2;2;1;2;1;2;2;2;4;3;4;1;5;4;2;0;0;0;0;0;0;0;0;0;0;4;4;4;4;4;0;0;0;0;0;0;0;
3;03.2012;7230;0;2;2;2;4;3;4;4;4;3;3;3;2;4;6;1;1;1;6;5;1;6;6;1;1;1;1;1;2;2;1;2;2;0;2;2;3;4;2;1;4;3;2;0;0;0;0;0;0;0;0;0;0;4;3;3;4;4;0;0;0;0;0;0;0;
3;03.2012;7231;0;1;3;1;4;4;3;3;4;4;4;4;2;5;5;1;1;4;6;5;1;4;1;1;1;1;1;5;2;1;1;2;0;0;1;2;4;4;3;1;4;3;2;0;0;0;0;0;0;0;0;0;0;4;4;4;4;3;0;0;0;0;0;0;0;

輸出:

pearl.342> awk -F";" 'BEGIN{OFS=";"} {$3="";print }' file3 | sed 's/;;/;/'
3;03.2012;0;1;3;1;3;4;3;1;3;4;3;2;0;4;4;1;1;4;2;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;1;1;3;0;3;1;3;0;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
3;03.2012;0;2;2;0;5;5;4;4;5;5;4;4;2;5;5;0;0;3;3;0;0;5;6;0;0;0;0;0;2;2;1;2;1;2;2;2;4;3;4;1;5;4;2;0;0;0;0;0;0;0;0;0;0;4;4;4;4;4;0;0;0;0;0;0;0;
3;03.2012;0;2;2;2;4;3;4;4;4;3;3;3;2;4;6;1;1;1;6;5;1;6;6;1;1;1;1;1;2;2;1;2;2;0;2;2;3;4;2;1;4;3;2;0;0;0;0;0;0;0;0;0;0;4;3;3;4;4;0;0;0;0;0;0;0;
3;03.2012;0;1;3;1;4;4;3;3;4;4;4;4;2;5;5;1;1;4;6;5;1;4;1;1;1;1;1;5;2;1;1;2;0;0;1;2;4;4;3;1;4;3;2;0;0;0;0;0;0;0;0;0;0;4;4;4;4;3;0;0;0;0;0;0;0;

我需要刪除字段3 ...是否有一個快捷方式可以說'$ 4 to the end'

是的,它基本上要求同樣的問題打印字段'N'到行尾

awk -F\\; '{print $1 FS $2 FS substr($0, index($0, $4))}' temp.txt

這也處理獎金問題

FS是字段分隔符,因此我的7個字段的文件輸出由';'分隔 如下

awk -F \\; '{print $ 1 FS $ 2 FS substr($ 0,index($ 0,$ 4))}'temp2

$> field1; field2; field4; field5; field6; field7

注意: 到最后的打印字段N自然保留了字段分隔符 - 至少據我所知

在進行測試時,我發現(如宣布的)我自己的sed解決方案:

sed -r 's/(([^;]*;){3}).;(.*)/\1\3/' a.txt > g.txt

如果你知道sed,不容易閱讀,但寫得容易。 看起來好像我要為我的問題找到2個解決方案:用一個程序刪除,用另一個程序轉換。

它刪除了字段3(如果我們碰巧從0開始計數,而不是1):)。

暫無
暫無

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

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