Vraag Hoe complete regel te lezen in 'voor' loop met spaties


Ik probeer een te rennen for loop voor bestand en ik wil de hele regel weergeven. Maar in plaats daarvan toont het alleen het laatste woord. Ik wil de complete lijn.

for j in `cat ./file_wget_med`

do
echo $j

done

resultaat na run:

Found.

Dit zijn mijn gegevens:

$ cat file_wget_med
2013-09-11 14:27:03 ERROR 404: Not Found.

94
2017-09-11 19:49


oorsprong


verwant: stackoverflow.com/questions/9084257/... - Ciro Santilli 新疆改造中心 六四事件 法轮功


antwoorden:


for loop splitst wanneer het een witruimte zoals spatie, tab of nieuwe lijn ziet. Dus je zou moeten gebruiken IFS (interne veldscheider):

IFS=$'\n'       # make newlines the only separator
for j in $(cat ./file_wget_med)    
do
    echo "$j"
done

134
2017-09-11 20:26



En let op enkele aanhalingstekens op IFS omdat IFS = $ "\ n" ook "nn" -reeksen zal splitsen. Ik vond set IFS betrouwbaarder dan ingewikkeldere syntaxis of functies gebruiken. - erm3nda
blijkbaar is het aan te raden om unset IFS achteraf, zodat andere opdrachten niet in dezelfde shell worden beïnvloed. - Boris Däppen
Wat doet de $ menen in IFS=$'\n'? - Ren
$ zorgt ervoor dat regeleinden in de string werken. Dit zou ook met moeten gebeuren local IFS=$'\n' binnen een functie. - Andy Ray
@Renn is dat $'...' bekend "ANSI-C Quoting" - αғsнιη


for loops worden standaard gesplitst in elke witruimte (spatie, tab, nieuwe regel); de gemakkelijkste manier om eraan te werken lijn tegelijkertijd is het gebruiken van een while read loop in plaats daarvan, die splitst op nieuwe regels:

while read i; do echo "$i"; done < ./file_wget_med

ik zou verwachten jouw opdracht om één woord per regel uit te spugen (dat gebeurde toen ik het uitteste met een eigen bestand). Als er iets anders aan de hand is, weet ik niet zeker wat het zou kunnen veroorzaken.


67
2017-09-11 20:04



Dit is ook een goed alternatief voor for i in `ls`; do echo $1; done, door de uitvoer naar de while-opdracht te pipen: ls|while read i; do echo $i; done. Dit werkt op bestands- / mapnamen met spaties, zonder omgevingsvariabelen te hoeven veranderen. Zeer goed antwoord. - jishi
de while heeft de eerste en laatste regel niet goed afgehandeld, niet zo goed als de for-lus met IFS - grantbow
@jishi Omdat het voornamelijk is ontworpen voor weergave en reageert op de grootte van het terminalvenster en dergelijke, ls wordt niet als veilig beschouwd voor gebruik met | (de pijpoperator). find is flexibeler naast het feit dat het veiliger is voor dit doel. - SeldomNeedy
Dit is een GEWELDIG antwoord, ik gebruikte het om een ​​lijst die ik had in PLIST-ingangen te veranderen voor een IOS-app die ik aan het ontwikkelen was op mac OSX. Ik heb de invoer van het bestand vervangen door het clipboad te gebruiken met pbpaste -> pbpaste | while read t; do echo "<string>$t</string>"; done - Big Rich
ls -1 kan worden gebruikt met | om één-per-regel ongeformatteerde uitvoer te garanderen - AndreyS Scherbakov


#!/bin/bash
files=`find <subdir> -name '*'`
while read -r fname; do
    echo $fname
done <<< "$files"

Geverifieerd werken, niet de enige voering die u waarschijnlijk wilt, maar het is niet mogelijk om dit elegant te doen.


16
2017-11-02 06:34



een here-string! meest elegante van alle andere oplossingen IMO - Eliran Malka


Hier is een kleine uitbreiding op het antwoord van Mitchell Currie, dat ik leuk vind vanwege de kleine hoeveelheid bijwerkingen, waardoor het niet nodig is om een ​​variabele in te stellen:

#!/bin/bash
while read -r fname; do
    echo $fname
done <<< "`find <subdir> -name '*'`"

3
2018-06-07 15:57





Ik zou het zo schrijven:

cat ./file_wget_med | while read -r j
do
    echo $j
done

omdat het de minste wijzigingen in het originele script vereist (behalve de oplossing die gebruikt IFS, maar het wijzigt bash gedrag niet alleen voor deze loop control statement).


0
2017-08-27 07:19