it-swarm-eu.dev

Jak opakovat řádky souboru?

Řekněme, že mám tento soubor:

hello
world
hello world

Tento program

#!/bin/bash

for i in $(cat $1); do
    echo "tester: $i"
done

výstupy

tester: hello
tester: world
tester: hello
tester: world

Chtěl bych mít iteraci for na každém řádku samostatně ignorující mezery, tj. Poslední dva řádky by měly být nahrazeny

tester: hello world

Použití uvozovek for i in "$(cat $1)"; má za následek, že i bude přiřazen celý soubor najednou. Co bych měl změnit?

63
Tobias Kienzler

S for a IFS :

#!/bin/bash

IFS=$'\n'       # make newlines the only separator
set -f          # disable globbing
for i in $(cat < "$1"); do
  echo "tester: $i"
done

Všimněte si však, že přeskočí prázdné řádky jako nový řádek jako znak IFS-white-space, jeho sekvence se počítají jako 1 a první a koncová jsou ignorováno. S zsh a ksh93 (ne bash), můžete jej změnit na IFS=$'\n\n' pro nový řádek, který nebude zpracován speciálně, ale všimněte si, že všechny koncové znaky nového řádku (tak, že zahrnuje koncové prázdné řádky) budou vždy odstraněny příkazem substituce.

Nebo s read (žádné další cat):

#!/bin/bash

while IFS= read -r line; do
  echo "tester: $line"
done < "$1"

Jsou zde zachovány prázdné řádky, ale všimněte si, že by přeskočilo poslední řádek, pokud by nebyl řádně ohraničen znakem nového řádku.

76
wag

Za to, co stojí za to, musím to dělat docela často a nikdy si nepamatuji přesný způsob použití while IFS= read..., takže jsem definoval následující funkci v mém bash profilu:

# iterate the line of a file and call input function
iterlines() {
    (( $# < 2 )) && { echo "Usage: iterlines <File> <Callback>"; return; }
    local File=$1
    local Func=$2
    n=$(cat "$File" | wc -l)
    for (( i=1; i<=n; i++ )); do
        "$Func" "$(sed "${i}q;d" "$File")"
    done
}

Tato funkce nejprve určí počet řádků v souboru, poté pomocí sed extrahuje řádek za řádkem a předá každý řádek jako argument s jediným řetězcem jakékoli dané funkci. Předpokládám, že by to mohlo být opravdu neefektivní s velkými soubory, ale to pro mě zatím nebyl problém (samozřejmě návrhy, jak toto přivítání zlepšit).

Použití je docela milé IMO:

>> cat example.txt # note the use of spaces, whitespace, etc.
a/path

This is a sentence.
"wi\th quotes"
$End
>> iterlines example.txt echo # preserves quotes, $ and whitespace
a/path

This is a sentence.
"wi\th quotes"
$End
>> x() { echo "$#"; }; iterlines example.txt x # line always passed as single input string
1
1 
1
1
1
1
Jonathan H