我正在尋找方法來計算可能是二進制資料的尾隨換行符的數量:
- 從標準輸入讀取
- 或者已經在使用 POSIX 或 coreutils 實用程式或 Perl 的 shell 變數中(當然“二進制”至少不包括 0x0)。
這應該在沒有臨時檔案或 FIFO 的情況下作業。
當輸入在 shell 變數中時,我已經有了以下(可能很難看但)可行的解決方案:
original_string=$'abc\n\n\def\n\n\n'
string_without_trailing_newlines="$( printf '%s' "${original_string}" )"
printf '%s' $(( ${#original_string}-${#string_without_trailing_newlines} ))
3在上面的例子中給出了。
上面的想法只是減去字串長度并使用命令替換的“功能”,即丟棄任何尾隨換行符。
uj5u.com熱心網友回復:
這是你想要的(使用 GNU awk)嗎?
$ printf 'ab\0c\n\0\n\d\0ef\n\n\n' | awk '/./{n=NR-1} END{print NR-n}'
3
uj5u.com熱心網友回復:
一些perl基于的解決方案:
#!/usr/bin/env bash
original_string=$'abc\n\n\ndef\n\n\n'
# From a shell variable. Look ma, no pipes!
input="$original_string" perl -E '$ENV{input} =~ /(\n*)\z/; say length $1'
# From standard input (Note: The herestring adds an extra newline)
perl -0777 -nE '/(\n*)\z/; say length($1) - 1' <<<"$original_string"
# Or in a shell without herestrings (But then you're also not getting the
# above $'' quoting syntax)
printf "%s" "$original_string" | perl -0777 -nE '/(\n*)\z/; say length $1'
還有一種更詳細的方式,它不涉及將輸入作為單個塊讀取-0777(除非根本沒有換行符),這對大量資料有好處:
printf "abc\n\ndef\n\n\n" | perl -nE '
if (/^\n\z/) { # Nothing but a newline
$blank
} elsif (/\n\z/) { # Data that ends in a newline; reset counter to 1
$blank = 1
} else { # No newline (Last line is missing one?); reset counter to 0
$blank = 0
}
END { say $blank }'
uj5u.com熱心網友回復:
使用 GNU sed,我們可以使用該-z選項,加上e替換命令的修飾符,并將所有這些打包在一個 sed 腳本中:
$ printf 'abc\n\n\def\n\n\n' | sed -Ezn '${s/.*[^\n]//;s/.*/wc -l <<!\n&!/ep}'
3
或者,如果字串在變數中:
$ printf '%s' "$original_string" | sed -Ezn '${s/.*[^\n]//;s/.*/wc -l <<!\n&!/ep}'
3
說明:
該
-z選項告訴 sed 輸入行以 NUL 字符而不是換行符終止。該
-n選項禁用自動列印。2 個替代命令僅應用于最后一行(
$地址),即最后一個 NUL 字符之后的所有內容,或者如果沒有 NUL 字符,則應用于完整的輸入字串。第一個替換命令洗掉除尾隨換行符之外的所有內容。
第二個替換命令將這些尾隨換行符替換為:
wc -l <<! !here-document 中的行數與輸入中的尾隨換行符一樣多。當使用
e修飾符時,這個新的模式空間被執行,模式空間被結果替換并列印(感謝p修飾符)。
uj5u.com熱心網友回復:
另一個 perl 解決方案怎么樣:
echo -ne 'abc\n\n\def\n\n\n' | perl -0777 -ne 'my $c = () = /(?<=\n)\n/g; print $c, "\n";'
輸出:
3
- 該
-0777選項告訴 perl 一次 slurp 所有輸入行。 - 該
-ne選項類似于的選項sed。 - 該陳述句
$c = () = /pattern/強制正則運算式運算子array context然后將 $c 分配給匹配計數。 - 正則運算式
(?<=\n)\n匹配前面有換行符的換行符。
uj5u.com熱心網友回復:
$ printf 'abc\n\ndef\n\n\n' | gawk 'END {print length(RT)}' RS='\n '
3
$ printf 'abc\n\ndef' | gawk 'END {print length(RT)}' RS='\n '
0
如果輸入已經在 shell 變數中,請使用引數擴展:
#! /bin/sh -
nl='
'
some_var="abc${nl}${nl}def${nl}${nl}${nl}"
trailing_nl=${some_var##*[!"$nl"]}
printf '%d\n' "${#trailing_nl}" # output: 3
some_var="abc${nl}${nl}def"
trailing_nl=${some_var##*[!"$nl"]}
printf '%d\n' "${#trailing_nl}" # output: 0
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/408882.html
標籤:
下一篇:在shell腳本中使用sed
