it-swarm-vi.com

Làm thế nào để tách nhiều không gian thành một bằng cách sử dụng sed?

sed trên AIX không hoạt động như tôi nghĩ. Tôi đang cố gắng thay thế nhiều không gian bằng một khoảng trống trong đầu ra của IOSTAT:

# iostat
System configuration: lcpu=4 drives=8 paths=2 vdisks=0

tty:      tin         tout    avg-cpu: % user % sys % idle % iowait
          0.2         31.8                9.7   4.9   82.9      2.5

Disks:        % tm_act     Kbps      tps    Kb_read   Kb_wrtn
hdisk9           0.2      54.2       1.1   1073456960  436765896
hdisk7           0.2      54.1       1.1   1070600212  435678280
hdisk8           0.0       0.0       0.0          0         0
hdisk6           0.0       0.0       0.0          0         0
hdisk1           0.1       6.3       0.5   63344916  112429672
hdisk0           0.1       5.0       0.2   40967838  98574444
cd0              0.0       0.0       0.0          0         0
hdiskpower1      0.2     108.3       2.3   2144057172  872444176

# iostat | grep hdisk1
hdisk1           0.1       6.3       0.5   63345700  112431123

#iostat|grep "hdisk1"|sed -e"s/[ ]*/ /g"
 h d i s k 1 0 . 1 6 . 3 0 . 5 6 3 3 4 5 8 8 0 1 1 2 4 3 2 3 5 4

sed nên tìm kiếm và thay thế (nhiều) nhiều khoảng trắng (/ [] * /) bằng một khoảng trắng (/ /) cho toàn bộ nhóm (/ g) ... nhưng nó không chỉ làm điều đó ... cách nhau từng ký tự.

Tôi đang làm gì sai? Tôi biết nó phải đơn giản ... AIX 5300-06

chỉnh sửa : Tôi có một máy tính khác có hơn 10 ổ cứng. Tôi đang sử dụng điều này như là một tham số cho một chương trình khác cho mục đích giám sát.

Vấn đề tôi gặp phải là "awk '{print $ 5}' không hoạt động vì tôi đang sử dụng $ 1, v.v. trong giai đoạn thứ cấp và đã gặp lỗi với lệnh In. Tôi đang tìm phiên bản grep/sed/cut Những gì dường như làm việc là:

iostat | grep "hdisk1 " | sed -e's/  */ /g' | cut -d" " -f 5

Các [] là "0 trở lên" khi tôi nghĩ chúng có nghĩa là "chỉ một". Loại bỏ các dấu ngoặc đã làm cho nó hoạt động. Ba câu trả lời rất hay thực sự nhanh chóng khiến bạn khó chọn "câu trả lời".

72
WernerCD

Việc sử dụng grep là không cần thiết, sed có thể làm tương tự. Vấn đề là ở việc sử dụng * cũng khớp 0 dấu cách, bạn phải sử dụng \+ thay thế:

iostat | sed -n '/hdisk1/s/ \+/ /gp'

Nếu sed của bạn không hỗ trợ \+ metachar, sau đó làm

iostat | sed -n '/hdisk1/s/  */ /gp'
57
enzotib

/[ ]*/ khớp không hoặc nhiều khoảng trắng, do đó, chuỗi trống giữa các ký tự khớp.

Nếu bạn đang cố gắng khớp "một hoặc nhiều khoảng trắng", hãy sử dụng một trong các dấu cách sau:

... | sed 's/  */ /g'
... | sed 's/ \{1,\}/ /g'
... | tr -s ' '
75
glenn jackman

Thay đổi toán tử * Của bạn thành +. Bạn đang khớp 0 hoặc nhiều ký tự trước đó, khớp với mọi ký tự bởi vì mọi thứ không phải là khoảng trắng là ... ừm ... không có không gian. Bạn cần phải khớp MỘT hoặc nhiều hơn. Trên thực tế sẽ tốt hơn nếu kết hợp hai hoặc nhiều hơn

Lớp ký tự được đặt trong ngoặc cũng không cần thiết để khớp một ký tự. Bạn chỉ có thể sử dụng:

s/  \+/ /g

... Trừ khi bạn muốn khớp các tab hoặc các loại khoảng trắng khác, thì lớp nhân vật là một ý tưởng hay.

15
Caleb

Bạn luôn có thể kết hợp lần xuất hiện cuối cùng trong một chuỗi bất kỳ thứ gì như:

s/\(sequence\)*/\1/

Và vì vậy, bạn đang đi đúng hướng, nhưng thay vì thay thế chuỗi bằng một khoảng trắng - thay thế nó bằng lần xuất hiện cuối cùng - một khoảng trắng. Theo cách đó, nếu một chuỗi các khoảng trắng is khớp thì chuỗi đó được giảm xuống một khoảng trắng, nhưng nếu chuỗi null được khớp thì chuỗi null được thay thế bằng chính nó - và không có hại, không có lỗi. Ví dụ:

sed 's/\( \)*/\1/g' <<\IN                                    
# iostat
System configuration: lcpu=4 drives=8 paths=2 vdisks=0

tty:      tin         tout    avg-cpu: % user % sys % idle % iowait
          0.2         31.8                9.7   4.9   82.9      2.5

Disks:        % tm_act     Kbps      tps    Kb_read   Kb_wrtn
hdisk9           0.2      54.2       1.1   1073456960  436765896
hdisk7           0.2      54.1       1.1   1070600212  435678280
hdisk8           0.0       0.0       0.0          0         0
hdisk6           0.0       0.0       0.0          0         0
hdisk1           0.1       6.3       0.5   63344916  112429672
hdisk0           0.1       5.0       0.2   40967838  98574444
cd0              0.0       0.0       0.0          0         0
hdiskpower1      0.2     108.3       2.3   2144057172  872444176

# iostat | grep hdisk1
hdisk1           0.1       6.3       0.5   63345700  112431123

IN

ĐẦU RA

# iostat
System configuration: lcpu=4 drives=8 paths=2 vdisks=0

tty: tin tout avg-cpu: % user % sys % idle % iowait
 0.2 31.8 9.7 4.9 82.9 2.5

Disks: % tm_act Kbps tps Kb_read Kb_wrtn
hdisk9 0.2 54.2 1.1 1073456960 436765896
hdisk7 0.2 54.1 1.1 1070600212 435678280
hdisk8 0.0 0.0 0.0 0 0
hdisk6 0.0 0.0 0.0 0 0
hdisk1 0.1 6.3 0.5 63344916 112429672
hdisk0 0.1 5.0 0.2 40967838 98574444
cd0 0.0 0.0 0.0 0 0
hdiskpower1 0.2 108.3 2.3 2144057172 872444176

# iostat | grep hdisk1
hdisk1 0.1 6.3 0.5 63345700 112431123

Tất cả những gì đã nói, có lẽ tốt hơn nhiều để tránh regexps hoàn toàn trong tình huống này và thay vào đó:

tr -s \  <infile
8
mikeserv

Lưu ý rằng bạn cũng có thể làm những gì bạn cố gắng, đó là

iostat | grep "hdisk1 " | sed -e's/  */ /g' | cut -d" " -f 5

bởi

iostat | while read disk tma kbps tps re wr; do [ "$disk" = "hdisk1" ] && echo "$re"; done

điều này có thể đặc biệt hữu ích nếu sau này bạn cũng cố gắng truy cập vào các trường khác và/hoặc tính toán một cái gì đó - như thế này:

iostat | while read disk tma kbps tps re wr; do [ "$disk" = "hdisk1" ] && echo "$(( re/1024 )) Mb"; done
5
rozcietrzewiacz

Bạn có thể sử dụng tập lệnh sau để chuyển đổi nhiều khoảng trắng thành một khoảng trắng, TAB hoặc bất kỳ chuỗi nào khác:

$ ls | compress_spaces.sh       # converts multiple spaces to one
$ ls | compress_spaces.sh TAB   # converts multiple spaces to a single tab character
$ ls | compress_spaces.sh TEST  # converts multiple spaces to the phrase TEST
$ compress_spaces.sh help       # show the help for this command

nén_spaces.sh

function show_help()
{
  IT=$(CAT <<EOF

  usage: {REPLACE_WITH}

  NOTE: If you pass in TAB, then multiple spaces are replaced with a TAB character

  no args -> multiple spaces replaced with a single space
  TAB     -> multiple spaces replaced with a single tab character
  TEST    -> multiple spaces replaced with the phrase "TEST"

  )
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi

# Show help if we're not getting data from stdin
if [ -t 0 ]; then
  show_help
fi

REPLACE_WITH=${1:-' '}

if [ "$REPLACE_WITH" == "tab" ]
then
  REPLACE_WITH=$'\t'
fi
if [ "$REPLACE_WITH" == "TAB" ]
then
  REPLACE_WITH=$'\t'
fi

sed "s/ \{1,\}/$REPLACE_WITH/gp"
0
Brad Parks