බෑෂ්: විචල්යයක රේඛා හරහා නැවත යෙදීම


255

යමෙකු විචල්‍යයකින් හෝ විධානයක ප්‍රතිදානයෙන් බාෂ් රේඛා හරහා නිසි ලෙස ක්‍රියා කරන්නේ කෙසේද? IFS විචල්‍යය නව පේළියකට සැකසීම විධානයක ප්‍රතිදානය සඳහා ක්‍රියා කරන නමුත් නව රේඛා අඩංගු විචල්‍යයක් සැකසීමේදී නොවේ.

උදාහරණයක් වශයෙන්

#!/bin/bash

list="One\ntwo\nthree\nfour"

#Print the list with echo
echo -e "echo: \n$list"

#Set the field separator to new line
IFS=$'\n'

#Try to iterate over each line
echo "For loop:"
for item in $list
do
        echo "Item: $item"
done

#Output the variable to a file
echo -e $list > list.txt

#Try to iterate over each line from the cat command
echo "For loop over command output:"
for item in `cat list.txt`
do
        echo "Item: $item"
done

මෙය ප්‍රතිදානය ලබා දෙයි:

echo: 
One
two
three
four
For loop:
Item: One\ntwo\nthree\nfour
For loop over command output:
Item: One
Item: two
Item: three
Item: four

ඔබට පෙනෙන පරිදි, විචල්‍යය ප්‍රතිරාවය කිරීම හෝ catවිධානය හරහා නැවත යෙදීම එක් එක් පේළි එකින් එක නිවැරදිව මුද්‍රණය කරයි. කෙසේ වෙතත්, පළමුවන ලූපය සියලු අයිතම තනි පේළියක මුද්‍රණය කරයි. අදහස් තිබේද?


සියලු පිළිතුරු සඳහා අදහස් දැක්වීමක් පමණි: නව රේඛා අක්‍ෂරය කැපීම සඳහා මට $ (echo "$ line" | sed -e's / ^ [[: space:]] * // ') කිරීමට සිදු විය.
servermanfail

Answers:


321

බෑෂ් සමඟ, ඔබට නව රේඛා නූලකට කාවැද්දීමට අවශ්‍ය නම්, ඒ සමඟ නූල කොටු කරන්න $'':

$ list="One\ntwo\nthree\nfour"
$ echo "$list"
One\ntwo\nthree\nfour
$ list=$'One\ntwo\nthree\nfour'
$ echo "$list"
One
two
three
four

ඔබට දැනටමත් එවැනි විචල්‍යයක් විචල්‍යයක තිබේ නම්, ඔබට එය රේඛීයව කියවිය හැකිය:

while IFS= read -r line; do
    echo "... $line ..."
done <<< "$list"

30
done <<< "$list"එය ඉතා වැදගත් බව සටහනක්
ජේසන් ඇක්සෙල්සන්

21
හේතුව done <<< "$list"ඉතා වැදගත් වන බව දක්වා ආදාන ලෙස "$ ලැයිස්තුව" සමත් වනු ඇත නිසා යread
wisbucky

24
මට මෙය අවධාරණය කිරීමට අවශ්‍යයි: ඩබල්-ක්වොටිං $listඉතා තීරණාත්මක ය.
ඇන්ඩ්‍රේ චලෙල්ලා

9
echo "$list" | while ...වඩා පැහැදිලි පෙනී සිටිය හැකි... done <<< "$line"
kyb

6
එම ප්‍රවේශය සඳහා අවාසි ඇත, නමුත් කාල ලූපය උප කුලකයක් තුළ ක්‍රියාත්මක වන බැවින්: ලූපයේ පවරා ඇති ඕනෑම විචල්‍යයන් නොපවතිනු ඇත.
ග්ලෙන් ජැක්මන්

75

ඔබට while+ read:

some_command | while read line ; do
   echo === $line ===
done

Btw. මෙම -eකිරීමට විකල්පය echoසම්මත නොවන වේ. printfඔබට අතේ ගෙන යා හැකි නම් ඒ වෙනුවට භාවිතා කරන්න .


14
ඔබ මෙම වාක්‍ය ඛණ්ඩය භාවිතා කරන්නේ නම්, ලූපය තුළ පවරා ඇති විචල්‍යයන් ලූපයෙන් පසුව නොගැලපෙන බව සලකන්න. නියමාකාර තරම්, මේ <<<ග්ලෙන් jackman විසින් යෝජනා අනුවාදය කරන්නේ විචල්ය පැවරුම සමග වැඩ.
ස්පාර්හෝක්

8
P ස්පාර්හෝක් ඔව්, එයට හේතුව නළය whileකොටස ක්‍රියාත්මක කරන උප කුලකයක් ආරම්භ කිරීමයි . මෙම <<<අනුවාදය (නව bash සංස්කරණවල, අවම වශයෙන්) නැහැ.
maxelost

36
#!/bin/sh

items="
one two three four
hello world
this should work just fine
"

IFS='
'
count=0
for item in $items
do
  count=$((count+1))
  echo $count $item
done

2
මෙය රේඛා නොව සියලු අයිතම ප්‍රතිදානය කරයි.
ටොමාස් පොසුස්නි

4
@ TomaszPosłuszny නැත, මෙය මගේ යන්ත්‍රයේ පේළි 3 (ගණන් 3) වේ. IFS හි සැකසුම සටහන් කරන්න. ඔබට IFS=$'\n'එකම බලපෑමක් සඳහා භාවිතා කළ හැකිය .
jmiserez

16

ඔබේ ලූපය සඳහා විහිලු ක්‍රමයක් මෙන්න:

for item in ${list//\\n/
}
do
   echo "Item: $item"
done

තව ටිකක් සංවේදී / කියවිය හැකි වනුයේ:

cr='
'
for item in ${list//\\n/$cr}
do
   echo "Item: $item"
done

නමුත් ඒ සියල්ල ඉතා සංකීර්ණයි, ඔබට අවශ්‍ය වන්නේ එහි ඉඩක් පමණි:

for item in ${list//\\n/ }
do
   echo "Item: $item"
done

ඔබේ $lineවිචල්‍යයේ නව රේඛා අඩංගු නොවේ. එය \අනුගමනය කළ අවස්ථා එහි අඩංගු වේ n. ඔබට එය පැහැදිලිව දැකගත හැකිය:

$ cat t.sh
#! /bin/bash
list="One\ntwo\nthree\nfour"
echo $list | hexdump -C

$ ./t.sh
00000000  4f 6e 65 5c 6e 74 77 6f  5c 6e 74 68 72 65 65 5c  |One\ntwo\nthree\|
00000010  6e 66 6f 75 72 0a                                 |nfour.|
00000016

ආදේශනය යනු අවකාශයන් ඇති අය වෙනුවට ආදේශ කිරීමයි, එය ලූප සඳහා වැඩ කිරීමට ප්‍රමාණවත් වේ:

$ cat t.sh
#! /bin/bash
list="One\ntwo\nthree\nfour"
echo ${list//\\n/ } | hexdump -C

$ ./t.sh 
00000000  4f 6e 65 20 74 77 6f 20  74 68 72 65 65 20 66 6f  |One two three fo|
00000010  75 72 0a                                          |ur.|
00000013

නිරූපණය:

$ cat t.sh
#! /bin/bash
list="One\ntwo\nthree\nfour"
echo ${list//\\n/ } | hexdump -C
for item in ${list//\\n/ } ; do
    echo $item
done

$ ./t.sh 
00000000  4f 6e 65 20 74 77 6f 20  74 68 72 65 65 20 66 6f  |One two three fo|
00000010  75 72 0a                                          |ur.|
00000013
One
two
three
four

සිත්ගන්නා කරුණ නම්, මෙහි සිදුවන්නේ කුමක්ද යන්න ඔබට පැහැදිලි කළ හැකිද? ඔබ line n නව පේළියකින් ආදේශ කරන බවක් පෙනේ ... මුල් නූල සහ නව එක අතර වෙනස කුමක්ද?
ඇලෙක්ස් ස්පර්ලින්

Lex ඇලෙක්ස්: මගේ පිළිතුර යාවත්කාලීන කරන ලදි - සරල අනුවාදයක් සමඟ :-)
මැට්

මම මෙය අත්හදා බැලූ අතර ඔබේ ආදානයේ ඉඩ තිබේ නම් එය ක්‍රියා කරන බවක් නොපෙනේ. ඉහත උදාහරණයේ අපට “එක් \ ntwo th nthree” ඇති අතර මෙය ක්‍රියාත්මක වන නමුත් අපට “ඇතුල්වීමේ එක් ent nentry two ent nentry three” තිබේ නම් එය අසාර්ථක වන අතර එය අවකාශයටද නව රේඛාවක් එක් කරයි.
ජෝන් රොචා

3
නිර්වචනය කරනවා වෙනුවට crඔබට භාවිතා කළ හැකි සටහනක් $'\n'.
devios1

මෙය වඩාත් නිවැරදි පිළිතුරයි. මෙම අනෙකුත් පිළිතුරු තුලට ලැබෙනු ඇත විචල්ය පිහිටුවා නැත හෝ හිස් වුවද පුඩුවක් .
මැරිනෝස්

3

ඔබට පළමුව විචල්‍යය අරාව බවට පරිවර්තනය කළ හැකිය, ඉන්පසු මෙය නැවත කියන්න.

lines="abc
def
ghi"

declare -a theArray

while read -r line
do
    theArray+=("$line")            
done <<< "$lines"

for line in "${theArray[@]}"
do
    echo "$line"
    #Do something complex here that would break your read loop
done

මෙය ප්‍රයෝජනවත් වන්නේ ඔබට අවුල් කිරීමට අවශ්‍ය නැතිනම් විධානය IFSසමඟ ගැටලු ඇති වුවහොත් පමණි read, එය සිදුවිය හැකි පරිදි, ඔබ වෙනත් ස්ක්‍රිප්ටයක් ලූපය තුළට කැඳවන්නේ නම්, එම ස්ක්‍රිප්ටයට නැවත පැමිණීමට පෙර ඔබේ කියවීමේ බෆරය හිස් කළ හැකිය. .

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.