ฉันจะแยกตัวอักษรของคำด้วยตัวอักษรแต่ละตัวในบรรทัดแยกกันได้อย่างไร
ตัวอย่างเช่นเมื่อ"StackOver"
ฉันต้องการที่จะเห็น
S
t
a
c
k
O
v
e
r
ฉันใหม่ในการทุบตีดังนั้นฉันไม่มีเงื่อนงำที่จะเริ่ม
ฉันจะแยกตัวอักษรของคำด้วยตัวอักษรแต่ละตัวในบรรทัดแยกกันได้อย่างไร
ตัวอย่างเช่นเมื่อ"StackOver"
ฉันต้องการที่จะเห็น
S
t
a
c
k
O
v
e
r
ฉันใหม่ในการทุบตีดังนั้นฉันไม่มีเงื่อนงำที่จะเริ่ม
คำตอบ:
ฉันจะใช้grep
:
$ grep -o . <<<"StackOver"
S
t
a
c
k
O
v
e
r
หรือsed
:
$ sed 's/./&\n/g' <<<"StackOver"
S
t
a
c
k
O
v
e
r
และถ้าพื้นที่ว่างท้ายเป็นปัญหา:
sed 's/\B/&\n/g' <<<"StackOver"
ทั้งหมดนี้คือสมมติว่า GNU / Linux
Here string
grosso modo เทียบเท่ากับการecho foo | ...
พิมพ์ที่น้อยลง ดูtldp.org/LDP/abs/html/x17837.html
.
เป็น\B
(ไม่ตรงกับขอบเขตของคำ)
sed
เช่น:sed -et -e's/./\n&/g;//D'
คุณอาจต้องการแบ่งกลุ่มของ grapheme แทนที่จะเป็นตัวอักษรหากเจตนาคือการพิมพ์ข้อความในแนวตั้ง เช่นกับ a e
ด้วยสำเนียงเฉียบพลัน:
ด้วยกลุ่มกราฟ ( e
ด้วยสำเนียงเฉียบพลันของมันจะเป็นหนึ่งกลุ่มแกรม):
$ perl -CLAS -le 'for (@ARGV) {print for /\X/g}' $'Ste\u301phane'
S
t
é
p
h
a
n
e
(หรือgrep -Po '\X'
ด้วย grep GNU ที่สร้างด้วยการรองรับ PCRE)
ด้วยตัวละคร (ที่นี่ด้วย GNU grep
):
$ printf '%s\n' $'Ste\u301phane' | grep -o .
S
t
e
p
h
a
n
e
fold
มีวัตถุประสงค์เพื่อแยกอักขระ แต่ GNU fold
ไม่รองรับอักขระหลายไบต์ดังนั้นจึงหยุดพักแบบไบต์แทน:
$ printf '%s\n' $'Ste\u301phane' | fold -w 1
S
t
e
�
�
p
h
a
n
e
บนStackOverซึ่งประกอบด้วยอักขระ ASCII เท่านั้น (ดังนั้นหนึ่งไบต์ต่ออักขระ, หนึ่งอักขระต่อคลัสเตอร์กราฟ) ทั้งสามจะให้ผลลัพธ์เดียวกัน
grep -Po
ไม่ได้ทำในสิ่งที่คาดหวัง (เหมือนgrep -P
)
grep -Po .
ค้นหาอักขระ (และการรวมกันของสำเนียงเฉียบพลันหลังจากอักขระบรรทัดใหม่ไม่ถูกต้อง) และgrep -Po '\X'
ค้นหากลุ่มกราฟสำหรับฉัน คุณอาจต้องรุ่นล่าสุดของ grep และ / หรือ PCRE เพื่อให้การทำงานอย่างถูกต้อง (หรือพยายามgrep -Po '(*UTF8)\X'
)
หากคุณมีperl6ในกล่องของคุณ:
$ perl6 -e 'for @*ARGS -> $w { .say for $w.comb }' 'cường'
c
ư
ờ
n
g
ทำงานโดยไม่คำนึงถึงสถานที่ของคุณ
มีหลายawk
รุ่น
awk -F '' -v OFS='\n' '{$1=$1};1' <<<'StackOver'
awk -v FS='' -v OFS='\n' '{$1=$1};1'
(สงสัยว่าถ้าเป็นแบบพกพามากขึ้นเนื่องจาก-F ''
อาจผลผลิต ERE: //
)
ด้านล่างจะเป็นแบบทั่วไป:
$ awk -F '' \
'BEGIN { RS = ""; OFS = "\n"} {for (i=1;i<=NF;i++) $i = $i; print }' <file_name>
echo StackOver | sed -e 's/./&\n/g'
S
t
a
c
k
O
v
e
r
เนื่องจากคุณขอคำตอบเป็นการเฉพาะในการทุบตีต่อไปนี้เป็นวิธีการใช้การทุบตีบริสุทธิ์:
while read -rn1; do echo "$REPLY" ; done <<< "StackOver"
โปรดทราบว่านี่จะขึ้นบรรทัดใหม่ในตอนท้ายของ " เอกสารที่นี่ " หากคุณต้องการหลีกเลี่ยงปัญหานั้น แต่ยังคงวนซ้ำอักขระที่มี bash loop ให้ใช้printf
เพื่อหลีกเลี่ยงการขึ้นบรรทัดใหม่
printf StackOver | while read -rn1; do echo "$REPLY" ; done
คุณสามารถใช้fold (1)
คำสั่ง มันจะมีประสิทธิภาพมากกว่าและgrep
sed
$ time grep -o . <bigfile >/dev/null
real 0m3.868s
user 0m3.784s
sys 0m0.056s
$ time fold -b1 <bigfile >/dev/null
real 0m0.555s
user 0m0.528s
sys 0m0.016s
$
ความแตกต่างที่สำคัญอย่างหนึ่งคือการพับที่จะสร้างบรรทัดว่างในเอาต์พุต:
$ grep -o . <(printf "A\nB\n\nC\n\n\nD\n")
A
B
C
D
$ fold -b1 <(printf "A\nB\n\nC\n\n\nD\n")
A
B
C
D
$
คุณสามารถจัดการอักขระหลายไบต์เช่น:
<input \
dd cbs=1 obs=2 conv=unblock |
sed -e:c -e '/^.*$/!N;s/\n//;tc'
ซึ่งจะมีประโยชน์สวยเมื่อคุณกำลังทำงานกับการถ่ายทอดสดการป้อนข้อมูลเพราะมีบัฟเฟอร์ไม่มีและตัวอักษรที่มีการพิมพ์เป็นเร็ว ๆ นี้ก็เป็นทั้ง
sed
สคริปต์สำหรับ ฉันไม่น่าจะเขียนเรื่องนี้เลยตอนนี้ - ฉันค่อนข้างง่วงนอน มันมีประโยชน์จริง ๆ เมื่ออ่านเทอร์มินัล
dd
จะแบ่งอักขระหลายไบต์ดังนั้นเอาต์พุตจะไม่เป็นข้อความอีกต่อไปดังนั้นพฤติกรรมของ sed จะไม่ได้รับการระบุตาม POSIX
คุณอาจใช้ขอบเขตของคำได้เช่นกัน ..
$ perl -pe 's/(?<=.)(\B|\b)(?=.)/\n/g' <<< "StackOver"
S
t
a
c
k
O
v
e
r
ในทุบตี:
สิ่งนี้ใช้ได้กับข้อความใด ๆ และมีเพียง bash internals (ไม่มียูทิลิตี้ภายนอกที่เรียกว่า) ดังนั้นควรรวดเร็วในสตริงที่สั้นมาก
str="Stéphane áàéèëêếe"
[[ $str =~ ${str//?/(.)} ]]
(set -- "${BASH_REMATCH[@]:1}"; IFS=$'\n'; echo "$*")
เอาท์พุท:
S
t
é
p
h
a
n
e
á
à
é
è
ë
ê
ế
e
หากการเปลี่ยน IFS และเปลี่ยนพารามิเตอร์ตำแหน่งคุณสามารถหลีกเลี่ยงการเรียก sub-shell ได้:
str="Stéphane áàéèëêếe"
[[ $str =~ ${str//?/(.)} ]]
set -- "${BASH_REMATCH[@]:1}"
IFS=$'\n'
echo "$*"
s=stackoverflow;
$ time echo $s | fold -w1
s
t
a
c
k
o
v
e
r
real 0m0.014s
user 0m0.000s
sys 0m0.004s
อัปเดต ที่นี่เป็นแฮ็ค | เร็วที่สุด | วิธี pureBashBased!
$ time eval eval printf \'%s\\\\n\' \\\${s:\{0..$((${#s}-1))}:1}
s
t
a
c
k
o
v
e
r
real 0m0.001s
user 0m0.000s
sys 0m0.000s
สำหรับสุดยอดมากขึ้น
function foldh ()
{
if (($#)); then
local s="$@";
eval eval printf \'%s\\\\n\' \\\"\\\${s:\{0..$((${#s}-1))}:1}\\\";
else
while read s; do
eval eval printf \'%s\\\\n\' \\\"\\\${s:\{0..$((${#s}-1))}:1}\\\";
done;
fi
}
function foldv ()
{
if (($#)); then
local s="$@";
eval eval echo \\\"\\\${s:\{0..$((${#s}-1))}:1}\\\";
else
while read s; do
eval eval echo \\\"\\\${s:\{0..$((${#s}-1))}:1}\\\";
done;
fi
}
fold -b1
หรือไม่
read -a var <<< $(echo "$yourWordhere" | grep -o "." | tr '\n' ' ')
var
นี้จะแยกคำของคุณและเก็บไว้ในอาร์เรย์
for x in $(echo "$yourWordhere" | grep -o '.')
do
code to perform operation on individual character $x of your word
done