जैसा कि नीचे बताया गया है, हमें अलग-अलग लंबाई की इनपुट फ़ाइल मिल रही है। पाठ अलग-अलग लंबाई का है।
इनपुट फ़ाइल:
ID|Text
1|name1=value1;name3;name4=value2;name5=value5
2|name1=value1;name2=value2;name6=;name7=value7;name8=value8
यहां टेक्स्ट ने वैल्यू पेयर को कंटेंट के रूप में नामित किया है और यह अलग-अलग लंबाई का है। कृपया ध्यान दें कि टेक्स्ट कॉलम में नाम में सेमी कोलन हो सकता है। हम इनपुट को पार्स करने की कोशिश कर रहे हैं लेकिन हम इसे एडब्ल्यूके या बाश के माध्यम से संभालने में सक्षम नहीं हैं
वांछित आउटपुट:
1|name1=value1
1|name3;name4=value2
1|name5=value5
2|name1=value1
2|name2=value2
2|name6=
2|name7=value7
2|name8=value8
नीचे दिया गया कोड आईडी = 2 के लिए काम करता है, लेकिन आईडी = 1 के लिए नहीं
echo "2|name1=value1;name2=value2;name6=;name7=value7;name8=value8" | while IFS="|"; read id text;do dsc=`echo $text|tr ';' '\n'`;echo "$dsc" >tmp;done
cat tmp
2|name1=value1
2|name2=value2
2|name6=
2|name7=value7
2|name8=value8
echo "1|name1=value1;name3;name4=value2;name5=value5" | while IFS="|"; read id text;do dsc=`echo $text|tr ';' '\n'`;echo "$dsc" >tmp;sed -i "s/^/${id}\|/g" tmp;done
cat tmp
1|name1=value1
1|name3
1|name4=value2
1|name5=value5
कोई भी मदद बहुत ही सराहनीय होगी।
5 जवाब
क्या आप जीएनयू awk
में दिखाए गए नमूनों के साथ इसके नए संस्करण के साथ निम्नलिखित, लिखित और परीक्षण करने का प्रयास कर सकते हैं। चूँकि OP का awk
संस्करण पुराना है, इसलिए यदि किसी के पास awk
का पुराना संस्करण है तो उसे awk --re-interval
में बदलने का प्रयास करें
awk '
BEGIN{
FS=OFS="|"
}
FNR==1{ next }
{
first=$1
while(match($0,/(name[0-9]+;?){1,}=(value[0-9]+)?/)){
print first,substr($0,RSTART,RLENGTH)
$0=substr($0,RSTART+RLENGTH)
}
}' Input_file
आउटपुट निम्नानुसार होगा।
1|name1=value1
1|name3;name4=value2
1|name5=value5
2|name1=value1
2|name2=value2
2|name6=
2|name7=value7
2|name8=value8
स्पष्टीकरण: ऊपर के लिए विस्तृत विवरण जोड़ना (निम्नलिखित केवल स्पष्टीकरण के उद्देश्य से है)।
awk ' ##Starting awk program from here.
BEGIN{ ##Starting BEGIN section from here.
FS=OFS="|" ##Setting FS and OFS wiht | here.
}
FNR==1{ next } ##If line is first line then go next, do not print anything.
{
first=$1 ##Creating first and setting as first field here.
while(match($0,/(name[0-9]+;?){1,}=(value[0-9]+)?/)){
##Running while loop which has match which has a regex of matching name and value all mentioned permutations and combinations.
print first,substr($0,RSTART,RLENGTH) ##Printing first and sub string(currently matched one)
$0=substr($0,RSTART+RLENGTH) ##Saving rest of the line into current line.
}
}' Input_file ##Mentioning Input_file name here.
BEGIN {FS = "[;|]"}
FNR == 1 {next}
{
sep = $1 "|"
for (i = 2; i <= NF; ++i) {
printf "%s%s", sep, $i
sep = ($i ~ /=/ ? ORS $1 "|" : ";")
}
print ""
}
आउटपुट (कोने के मामलों वाली एक इनपुट फ़ाइल दी गई है):
$ cat test_file
ID|Text
1|name1=value1;name3;name4=value2;Test1
2|Test2;name2=value2;name6=;name7=value7;Test3
$ awk -f prog.awk test_file
1|name1=value1
1|name3;name4=value2
1|Test1
2|Test2;name2=value2
2|name6=
2|name7=value7
2|Test3
आपके पास कुछ अच्छे उत्तर हैं और एक स्वीकृत पहले से ही है। यहाँ एक बहुत छोटा gnu awk कमांड है जो काम भी कर सकता है:
awk -F '|' 'NR > 1 {
for (s=$2; match(s, /([^=]+=[^;]*)(;|$)/, m); s=substr(s, RLENGTH+1))
print $1 FS m[1]
}' file.txt
1|name1=value1
1|name3;name4=value2
1|name5=value5
2|name1=value1
2|name2=value2
2|name6=
2|name7=value7
2|name8=value8
एक बैश समाधान:
#!/usr/bin/env bash
while IFS=\| read -r id text || [ -n "$id" ]; do
IFS=\; read -r -a kv_arr < <(printf %s "$text")
printf "$id|%s\\n" "${kv_arr[@]}"
done < <(tail -n +2 a.txt)
एक सादा पॉज़िक्स खोल समाधान:
#!/usr/bin/env sh
# Chop the header line from the input file
tail -n +2 a.txt |
# While reading id and text Fields Separated by vertical bar
while IFS=\| read -r id text || [ -n "$id" ]; do
# Sets the separator to a semicolon
IFS=\;
# Print each semicolon separated field formatted on
# its own line with the ID
# shellcheck disable=SC2086 # Explicit split on semicolon
printf "$id|%s\\n" $text
done
इनपुट a.txt
:
ID|Text
1|name1=value1;name3;name4=value2;name5=value5
2|name1=value1;name2=value2;name6=;name7=value7;name8=value8
आउटपुट:
1|name1=value1
1|name3
1|name4=value2
1|name5=value5
2|name1=value1
2|name2=value2
2|name6=
2|name7=value7
2|name8=value8
नमूना डेटा:
$ cat name.dat
ID|Text
1|name1=value1;name3;name4=value2;name5=value5
2|name1=value1;name2=value2;name6=;name7=value7;name8=value8
एक awk
समाधान:
awk -F"[|;]" ' # use "|" and ";" as input field delimiters
FNR==1 { next } # skip header line
{ pfx=$1 "|" # set output prefix to field 1 + "|"
printpfx=1 # set flag to print prefix
for ( i=2 ; i<=NF ; i++ ) # for fields 2 to NF
{
if ( printpfx) { printf "%s", pfx ; printpfx=0 } # if print flag == 1 then print prefix and clear flag
if ( $(i) ~ /=/ ) { printf "%s\n", $(i) ; printpfx=1 } # if current field contains "=" then print it, end this line of output, reset print flag == 1
if ( $(i) !~ /=/ ) { printf "%s;", $(i) } # if current field does not contain "=" then print it and include a ";" suffix
}
}
' name.dat
उपरोक्त उत्पन्न करता है:
1|name1=value1
1|name3;name4=value2
1|name5=value5
2|name1=value1
2|name2=value2
2|name6=
2|name7=value7
2|name8=value8
संबंधित सवाल
नए सवाल
bash
बैश कमांड शेल के लिए लिखी गई लिपियों के बारे में प्रश्नों के लिए। त्रुटियों / वाक्यविन्यास त्रुटियों के साथ शेल स्क्रिप्ट के लिए, कृपया यहां पोस्ट करने से पहले शेलचेक प्रोग्राम (या वेब शेलचेक सर्वर पर https://shellcheck.net) के साथ उन्हें जांचें। बैश के इंटरैक्टिव उपयोग के बारे में सवाल स्टैक ओवरफ्लो की तुलना में सुपर उपयोगकर्ता पर ऑन-टॉपिक होने की अधिक संभावना है।